#define SQLITE_MAX_EXPR_DEPTH

using System;
using System.Diagnostics;
using i16 = System.Int16;
using u16 = System.UInt16;
using u8 = System.Byte;

namespace Community.CsharpSqlite
{
	public partial class Sqlite3
	{
		/*
		** 2001 September 15
		**
		** The author disclaims copyright to this source code.  In place of
		** a legal notice, here is a blessing:
		**
		**    May you do good and not evil.
		**    May you find forgiveness for yourself and forgive others.
		**    May you share freely, never taking more than you give.
		**
		*************************************************************************
		** This file contains C code routines that are called by the parser
		** to handle SELECT statements in SQLite.
		*************************************************************************
		**  Included in SQLite3 port to C#-SQLite;  2008 Noah B Hart
		**  C#-SQLite is an independent reimplementation of the SQLite software library
		**
		**  SQLITE_SOURCE_ID: 2011-06-23 19:49:22 4374b7e83ea0a3fbc3691f9c0c936272862f32f2
		**
		*************************************************************************
		*/
		//#include "sqliteInt.h"

		/*
		** Delete all the content of a Select structure but do not deallocate
		** the select structure itself.
		*/

		private static void clearSelect(sqlite3 db, Select p)
		{
			sqlite3ExprListDelete(db, ref p.pEList);
			sqlite3SrcListDelete(db, ref p.pSrc);
			sqlite3ExprDelete(db, ref p.pWhere);
			sqlite3ExprListDelete(db, ref p.pGroupBy);
			sqlite3ExprDelete(db, ref p.pHaving);
			sqlite3ExprListDelete(db, ref p.pOrderBy);
			sqlite3SelectDelete(db, ref p.pPrior);
			sqlite3ExprDelete(db, ref p.pLimit);
			sqlite3ExprDelete(db, ref p.pOffset);
		}

		/*
		** Initialize a SelectDest structure.
		*/

		private static void sqlite3SelectDestInit(SelectDest pDest, int eDest, int iParm)
		{
			pDest.eDest = (u8)eDest;
			pDest.iParm = iParm;
			pDest.affinity = '\0';
			pDest.iMem = 0;
			pDest.nMem = 0;
		}

		/*
		** Allocate a new Select structure and return a pointer to that
		** structure.
		*/

		// OVERLOADS, so I don't need to rewrite parse.c
		private static Select sqlite3SelectNew(Parse pParse, int null_2, SrcList pSrc, int null_4, int null_5, int null_6, int null_7, int isDistinct, int null_9, int null_10)
		{
			return sqlite3SelectNew(pParse, null, pSrc, null, null, null, null, isDistinct, null, null);
		}

		private static Select sqlite3SelectNew(
		Parse pParse,        /* Parsing context */
		ExprList pEList,     /* which columns to include in the result */
		SrcList pSrc,        /* the FROM clause -- which tables to scan */
		Expr pWhere,         /* the WHERE clause */
		ExprList pGroupBy,   /* the GROUP BY clause */
		Expr pHaving,        /* the HAVING clause */
		ExprList pOrderBy,   /* the ORDER BY clause */
		int isDistinct,       /* true if the DISTINCT keyword is present */
		Expr pLimit,         /* LIMIT value.  NULL means not used */
		Expr pOffset         /* OFFSET value.  NULL means no offset */
		)
		{
			Select pNew;
			//           Select standin;
			sqlite3 db = pParse.db;
			pNew = new Select();//sqlite3DbMallocZero(db, sizeof(*pNew) );
			Debug.Assert( //db.mallocFailed != 0 ||
			null == pOffset || pLimit != null); /* OFFSET implies LIMIT */
			//if( pNew==null   ){
			//  pNew = standin;
			//  memset(pNew, 0, sizeof(*pNew));
			//}
			if (pEList == null)
			{
				pEList = sqlite3ExprListAppend(pParse, null, sqlite3Expr(db, TK_ALL, null));
			}
			pNew.pEList = pEList;
			pNew.pSrc = pSrc;
			pNew.pWhere = pWhere;
			pNew.pGroupBy = pGroupBy;
			pNew.pHaving = pHaving;
			pNew.pOrderBy = pOrderBy;
			pNew.selFlags = (u16)(isDistinct != 0 ? SF_Distinct : 0);
			pNew.op = TK_SELECT;
			pNew.pLimit = pLimit;
			pNew.pOffset = pOffset;
			Debug.Assert(pOffset == null || pLimit != null);
			pNew.addrOpenEphm[0] = -1;
			pNew.addrOpenEphm[1] = -1;
			pNew.addrOpenEphm[2] = -1;
			//if ( db.mallocFailed != 0 )
			//{
			//  clearSelect( db, pNew );
			//  //if ( pNew != standin ) sqlite3DbFree( db, ref pNew );
			//  pNew = null;
			//}
			return pNew;
		}

		/*
		** Delete the given Select structure and all of its substructures.
		*/

		private static void sqlite3SelectDelete(sqlite3 db, ref Select p)
		{
			if (p != null)
			{
				clearSelect(db, p);
				sqlite3DbFree(db, ref p);
			}
		}

		/*
		** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the
		** type of join.  Return an integer constant that expresses that type
		** in terms of the following bit values:
		**
		**     JT_INNER
		**     JT_CROSS
		**     JT_OUTER
		**     JT_NATURAL
		**     JT_LEFT
		**     JT_RIGHT
		**
		** A full outer join is the combination of JT_LEFT and JT_RIGHT.
		**
		** If an illegal or unsupported join type is seen, then still return
		** a join type, but put an error in the pParse structure.
		*/

		private class Keyword
		{
			public u8 i;        /* Beginning of keyword text in zKeyText[] */
			public u8 nChar;    /* Length of the keyword in characters */
			public u8 code;     /* Join type mask */

			public Keyword(u8 i, u8 nChar, u8 code)
			{
				this.i = i;
				this.nChar = nChar;
				this.code = code;
			}
		}

		// OVERLOADS, so I don't need to rewrite parse.c
		private static int sqlite3JoinType(Parse pParse, Token pA, int null_3, int null_4)
		{
			return sqlite3JoinType(pParse, pA, null, null);
		}

		private static int sqlite3JoinType(Parse pParse, Token pA, Token pB, int null_4)
		{
			return sqlite3JoinType(pParse, pA, pB, null);
		}

		private static int sqlite3JoinType(Parse pParse, Token pA, Token pB, Token pC)
		{
			int jointype = 0;
			Token[] apAll = new Token[3];
			Token p;

			/*   0123456789 123456789 123456789 123 */
			string zKeyText = "naturaleftouterightfullinnercross";

			Keyword[] aKeyword = new Keyword[]{
/* natural */ new Keyword( 0,  7, JT_NATURAL                ),
/* left    */ new Keyword( 6,  4, JT_LEFT|JT_OUTER          ),
/* outer   */ new Keyword( 10, 5, JT_OUTER                  ),
/* right   */ new Keyword( 14, 5, JT_RIGHT|JT_OUTER         ),
/* full    */ new Keyword( 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER ),
/* inner   */ new Keyword( 23, 5, JT_INNER                  ),
/* cross   */ new Keyword( 28, 5, JT_INNER|JT_CROSS         ),
};
			int i, j;
			apAll[0] = pA;
			apAll[1] = pB;
			apAll[2] = pC;
			for (i = 0; i < 3 && apAll[i] != null; i++)
			{
				p = apAll[i];
				for (j = 0; j < ArraySize(aKeyword); j++)
				{
					if (p.n == aKeyword[j].nChar
					&& p.z.StartsWith(zKeyText.Substring(aKeyword[j].i, aKeyword[j].nChar), StringComparison.OrdinalIgnoreCase))
					{
						jointype |= aKeyword[j].code;
						break;
					}
				}
				testcase(j == 0 || j == 1 || j == 2 || j == 3 || j == 4 || j == 5 || j == 6);
				if (j >= ArraySize(aKeyword))
				{
					jointype |= JT_ERROR;
					break;
				}
			}
			if (
			(jointype & (JT_INNER | JT_OUTER)) == (JT_INNER | JT_OUTER) ||
			(jointype & JT_ERROR) != 0
			)
			{
				string zSp = " ";
				Debug.Assert(pB != null);
				if (pC == null)
				{
					zSp = "";
				}
				sqlite3ErrorMsg(pParse, "unknown or unsupported join type: " +
				"%T %T%s%T", pA, pB, zSp, pC);
				jointype = JT_INNER;
			}
			else if ((jointype & JT_OUTER) != 0
			&& (jointype & (JT_LEFT | JT_RIGHT)) != JT_LEFT)
			{
				sqlite3ErrorMsg(pParse,
				"RIGHT and FULL OUTER JOINs are not currently supported");
				jointype = JT_INNER;
			}
			return jointype;
		}

		/*
		** Return the index of a column in a table.  Return -1 if the column
		** is not contained in the table.
		*/

		private static int columnIndex(Table pTab, string zCol)
		{
			int i;
			for (i = 0; i < pTab.nCol; i++)
			{
				if (pTab.aCol[i].zName.Equals(zCol, StringComparison.OrdinalIgnoreCase))
					return i;
			}
			return -1;
		}

		/*
		** Search the first N tables in pSrc, from left to right, looking for a
		** table that has a column named zCol.
		**
		** When found, set *piTab and *piCol to the table index and column index
		** of the matching column and return TRUE.
		**
		** If not found, return FALSE.
		*/

		private static int tableAndColumnIndex(
		SrcList pSrc,        /* Array of tables to search */
		int N,               /* Number of tables in pSrc.a[] to search */
		string zCol,         /* Name of the column we are looking for */
		ref int piTab,       /* Write index of pSrc.a[] here */
		ref int piCol        /* Write index of pSrc.a[*piTab].pTab.aCol[] here */
		)
		{
			int i;               /* For looping over tables in pSrc */
			int iCol;            /* Index of column matching zCol */

			Debug.Assert((piTab == 0) == (piCol == 0));  /* Both or neither are NULL */
			for (i = 0; i < N; i++)
			{
				iCol = columnIndex(pSrc.a[i].pTab, zCol);
				if (iCol >= 0)
				{
					//if( piTab )
					{
						piTab = i;
						piCol = iCol;
					}
					return 1;
				}
			}
			return 0;
		}

		/*
		** This function is used to add terms implied by JOIN syntax to the
		** WHERE clause expression of a SELECT statement. The new term, which
		** is ANDed with the existing WHERE clause, is of the form:
		**
		**    (vtab1.col1 = tab2.col2)
		**
		** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the
		** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is
		** column iColRight of tab2.
		*/

		private static void addWhereTerm(
		Parse pParse,                   /* Parsing context */
		SrcList pSrc,                   /* List of tables in FROM clause */
		int iLeft,                      /* Index of first table to join in pSrc */
		int iColLeft,                   /* Index of column in first table */
		int iRight,                     /* Index of second table in pSrc */
		int iColRight,                  /* Index of column in second table */
		int isOuterJoin,                /* True if this is an OUTER join */
		ref Expr ppWhere                /* IN/OUT: The WHERE clause to add to */
		)
		{
			sqlite3 db = pParse.db;
			Expr pE1;
			Expr pE2;
			Expr pEq;

			Debug.Assert(iLeft < iRight);
			Debug.Assert(pSrc.nSrc > iRight);
			Debug.Assert(pSrc.a[iLeft].pTab != null);
			Debug.Assert(pSrc.a[iRight].pTab != null);

			pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft);
			pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight);

			pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0);
			if (pEq != null && isOuterJoin != 0)
			{
				ExprSetProperty(pEq, EP_FromJoin);
				Debug.Assert(!ExprHasAnyProperty(pEq, EP_TokenOnly | EP_Reduced));
				ExprSetIrreducible(pEq);
				pEq.iRightJoinTable = (i16)pE2.iTable;
			}
			ppWhere = sqlite3ExprAnd(db, ppWhere, pEq);
		}

		/*
		** Set the EP_FromJoin property on all terms of the given expression.
		** And set the Expr.iRightJoinTable to iTable for every term in the
		** expression.
		**
		** The EP_FromJoin property is used on terms of an expression to tell
		** the LEFT OUTER JOIN processing logic that this term is part of the
		** join restriction specified in the ON or USING clause and not a part
		** of the more general WHERE clause.  These terms are moved over to the
		** WHERE clause during join processing but we need to remember that they
		** originated in the ON or USING clause.
		**
		** The Expr.iRightJoinTable tells the WHERE clause processing that the
		** expression depends on table iRightJoinTable even if that table is not
		** explicitly mentioned in the expression.  That information is needed
		** for cases like this:
		**
		**    SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5
		**
		** The where clause needs to defer the handling of the t1.x=5
		** term until after the t2 loop of the join.  In that way, a
		** NULL t2 row will be inserted whenever t1.x!=5.  If we do not
		** defer the handling of t1.x=5, it will be processed immediately
		** after the t1 loop and rows with t1.x!=5 will never appear in
		** the output, which is incorrect.
		*/

		private static void setJoinExpr(Expr p, int iTable)
		{
			while (p != null)
			{
				ExprSetProperty(p, EP_FromJoin);
				Debug.Assert(!ExprHasAnyProperty(p, EP_TokenOnly | EP_Reduced));
				ExprSetIrreducible(p);
				p.iRightJoinTable = (i16)iTable;
				setJoinExpr(p.pLeft, iTable);
				p = p.pRight;
			}
		}

		/*
		** This routine processes the join information for a SELECT statement.
		** ON and USING clauses are converted into extra terms of the WHERE clause.
		** NATURAL joins also create extra WHERE clause terms.
		**
		** The terms of a FROM clause are contained in the Select.pSrc structure.
		** The left most table is the first entry in Select.pSrc.  The right-most
		** table is the last entry.  The join operator is held in the entry to
		** the left.  Thus entry 0 contains the join operator for the join between
		** entries 0 and 1.  Any ON or USING clauses associated with the join are
		** also attached to the left entry.
		**
		** This routine returns the number of errors encountered.
		*/

		private static int sqliteProcessJoin(Parse pParse, Select p)
		{
			SrcList pSrc;                  /* All tables in the FROM clause */
			int i;
			int j;                       /* Loop counters */
			SrcList_item pLeft;     /* Left table being joined */
			SrcList_item pRight;    /* Right table being joined */

			pSrc = p.pSrc;
			//pLeft = pSrc.a[0];
			//pRight = pLeft[1];
			for (i = 0; i < pSrc.nSrc - 1; i++)
			{
				pLeft = pSrc.a[i]; // pLeft ++
				pRight = pSrc.a[i + 1];//Right++,
				Table pLeftTab = pLeft.pTab;
				Table pRightTab = pRight.pTab;
				bool isOuter;

				if (NEVER(pLeftTab == null || pRightTab == null))
					continue;
				isOuter = (pRight.jointype & JT_OUTER) != 0;

				/* When the NATURAL keyword is present, add WHERE clause terms for
				** every column that the two tables have in common.
				*/
				if ((pRight.jointype & JT_NATURAL) != 0)
				{
					if (pRight.pOn != null || pRight.pUsing != null)
					{
						sqlite3ErrorMsg(pParse, "a NATURAL join may not have " +
						"an ON or USING clause", "");
						return 1;
					}
					for (j = 0; j < pRightTab.nCol; j++)
					{
						string zName;      /* Name of column in the right table */
						int iLeft = 0;     /* Matching left table */
						int iLeftCol = 0;  /* Matching column in the left table */

						zName = pRightTab.aCol[j].zName;
						int iRightCol = columnIndex(pRightTab, zName);
						if (tableAndColumnIndex(pSrc, i + 1, zName, ref iLeft, ref iLeftCol) != 0)
						{
							addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i + 1, j,
							isOuter ? 1 : 0, ref p.pWhere);
						}
					}
				}

				/* Disallow both ON and USING clauses in the same join
				*/
				if (pRight.pOn != null && pRight.pUsing != null)
				{
					sqlite3ErrorMsg(pParse, "cannot have both ON and USING " +
					"clauses in the same join");
					return 1;
				}

				/* Add the ON clause to the end of the WHERE clause, connected by
				** an AND operator.
				*/
				if (pRight.pOn != null)
				{
					if (isOuter)
						setJoinExpr(pRight.pOn, pRight.iCursor);
					p.pWhere = sqlite3ExprAnd(pParse.db, p.pWhere, pRight.pOn);
					pRight.pOn = null;
				}

				/* Create extra terms on the WHERE clause for each column named
				** in the USING clause.  Example: If the two tables to be joined are
				** A and B and the USING clause names X, Y, and Z, then add this
				** to the WHERE clause:    A.X=B.X AND A.Y=B.Y AND A.Z=B.Z
				** Report an error if any column mentioned in the USING clause is
				** not contained in both tables to be joined.
				*/
				if (pRight.pUsing != null)
				{
					IdList pList = pRight.pUsing;
					for (j = 0; j < pList.nId; j++)
					{
						string zName;        /* Name of the term in the USING clause */
						int iLeft = 0;       /* Table on the left with matching column name */
						int iLeftCol = 0;    /* Column number of matching column on the left */
						int iRightCol;       /* Column number of matching column on the right */

						zName = pList.a[j].zName;
						iRightCol = columnIndex(pRightTab, zName);
						if (iRightCol < 0
						|| 0 == tableAndColumnIndex(pSrc, i + 1, zName, ref iLeft, ref iLeftCol)
						)
						{
							sqlite3ErrorMsg(pParse, "cannot join using column %s - column " +
							"not present in both tables", zName);
							return 1;
						}
						addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i + 1, iRightCol,
						isOuter ? 1 : 0, ref p.pWhere);
					}
				}
			}
			return 0;
		}

		/*
		** Insert code into "v" that will push the record on the top of the
		** stack into the sorter.
		*/

		private static void pushOntoSorter(
		Parse pParse,         /* Parser context */
		ExprList pOrderBy,    /* The ORDER BY clause */
		Select pSelect,       /* The whole SELECT statement */
		int regData           /* Register holding data to be sorted */
		)
		{
			Vdbe v = pParse.pVdbe;
			int nExpr = pOrderBy.nExpr;
			int regBase = sqlite3GetTempRange(pParse, nExpr + 2);
			int regRecord = sqlite3GetTempReg(pParse);
			sqlite3ExprCacheClear(pParse);
			sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, false);
			sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy.iECursor, regBase + nExpr);
			sqlite3ExprCodeMove(pParse, regData, regBase + nExpr + 1, 1);
			sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);
			sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy.iECursor, regRecord);
			sqlite3ReleaseTempReg(pParse, regRecord);
			sqlite3ReleaseTempRange(pParse, regBase, nExpr + 2);
			if (pSelect.iLimit != 0)
			{
				int addr1, addr2;
				int iLimit;
				if (pSelect.iOffset != 0)
				{
					iLimit = pSelect.iOffset + 1;
				}
				else
				{
					iLimit = pSelect.iLimit;
				}
				addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit);
				sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);
				addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
				sqlite3VdbeJumpHere(v, addr1);
				sqlite3VdbeAddOp1(v, OP_Last, pOrderBy.iECursor);
				sqlite3VdbeAddOp1(v, OP_Delete, pOrderBy.iECursor);
				sqlite3VdbeJumpHere(v, addr2);
			}
		}

		/*
		** Add code to implement the OFFSET
		*/

		private static void codeOffset(
		Vdbe v,          /* Generate code into this VM */
		Select p,        /* The SELECT statement being coded */
		int iContinue    /* Jump here to skip the current record */
		)
		{
			if (p.iOffset != 0 && iContinue != 0)
			{
				int addr;
				sqlite3VdbeAddOp2(v, OP_AddImm, p.iOffset, -1);
				addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p.iOffset);
				sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue);
#if SQLITE_DEBUG
				VdbeComment(v, "skip OFFSET records");
#endif
				sqlite3VdbeJumpHere(v, addr);
			}
		}

		/*
		** Add code that will check to make sure the N registers starting at iMem
		** form a distinct entry.  iTab is a sorting index that holds previously
		** seen combinations of the N values.  A new entry is made in iTab
		** if the current N values are new.
		**
		** A jump to addrRepeat is made and the N+1 values are popped from the
		** stack if the top N elements are not distinct.
		*/

		private static void codeDistinct(
		Parse pParse,     /* Parsing and code generating context */
		int iTab,          /* A sorting index used to test for distinctness */
		int addrRepeat,    /* Jump to here if not distinct */
		int N,             /* Number of elements */
		int iMem           /* First element */
		)
		{
			Vdbe v;
			int r1;

			v = pParse.pVdbe;
			r1 = sqlite3GetTempReg(pParse);
			sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N);
			sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
			sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1);
			sqlite3ReleaseTempReg(pParse, r1);
		}

#if !SQLITE_OMIT_SUBQUERY
		/*
** Generate an error message when a SELECT is used within a subexpression
** (example:  "a IN (SELECT * FROM table)") but it has more than 1 result
** column.  We do this in a subroutine because the error used to occur
** in multiple places.  (The error only occurs in one place now, but we
** retain the subroutine to minimize code disruption.)
*/

		private static bool checkForMultiColumnSelectError(
		Parse pParse,       /* Parse context. */
		SelectDest pDest,   /* Destination of SELECT results */
		int nExpr           /* Number of result columns returned by SELECT */
		)
		{
			int eDest = pDest.eDest;
			if (nExpr > 1 && (eDest == SRT_Mem || eDest == SRT_Set))
			{
				sqlite3ErrorMsg(pParse, "only a single result allowed for " +
				"a SELECT that is part of an expression");
				return true;
			}
			else
			{
				return false;
			}
		}

#endif

		/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.
**
** If srcTab and nColumn are both zero, then the pEList expressions
** are evaluated in order to get the data for this row.  If nColumn>0
** then data is pulled from srcTab and pEList is used only to get the
** datatypes for each column.
*/

		private static void selectInnerLoop(
		Parse pParse,          /* The parser context */
		Select p,              /* The complete select statement being coded */
		ExprList pEList,       /* List of values being extracted */
		int srcTab,            /* Pull data from this table */
		int nColumn,           /* Number of columns in the source table */
		ExprList pOrderBy,     /* If not NULL, sort results using this key */
		int distinct,          /* If >=0, make sure results are distinct */
		SelectDest pDest,      /* How to dispose of the results */
		int iContinue,         /* Jump here to continue with next row */
		int iBreak             /* Jump here to break out of the inner loop */
		)
		{
			Vdbe v = pParse.pVdbe;
			int i;
			bool hasDistinct;         /* True if the DISTINCT keyword is present */
			int regResult;            /* Start of memory holding result set */
			int eDest = pDest.eDest;  /* How to dispose of results */
			int iParm = pDest.iParm;  /* First argument to disposal method */
			int nResultCol;           /* Number of result columns */

			Debug.Assert(v != null);
			if (NEVER(v == null))
				return;
			Debug.Assert(pEList != null);
			hasDistinct = distinct >= 0;
			if (pOrderBy == null && !hasDistinct)
			{
				codeOffset(v, p, iContinue);
			}

			/* Pull the requested columns.
			*/
			if (nColumn > 0)
			{
				nResultCol = nColumn;
			}
			else
			{
				nResultCol = pEList.nExpr;
			}
			if (pDest.iMem == 0)
			{
				pDest.iMem = pParse.nMem + 1;
				pDest.nMem = nResultCol;
				pParse.nMem += nResultCol;
			}
			else
			{
				Debug.Assert(pDest.nMem == nResultCol);
			}
			regResult = pDest.iMem;
			if (nColumn > 0)
			{
				for (i = 0; i < nColumn; i++)
				{
					sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult + i);
				}
			}
			else if (eDest != SRT_Exists)
			{
				/* If the destination is an EXISTS(...) expression, the actual
				** values returned by the SELECT are not required.
				*/
				sqlite3ExprCacheClear(pParse);
				sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest == SRT_Output);
			}
			nColumn = nResultCol;

			/* If the DISTINCT keyword was present on the SELECT statement
			** and this row has been seen before, then do not make this row
			** part of the result.
			*/
			if (hasDistinct)
			{
				Debug.Assert(pEList != null);
				Debug.Assert(pEList.nExpr == nColumn);
				codeDistinct(pParse, distinct, iContinue, nColumn, regResult);
				if (pOrderBy == null)
				{
					codeOffset(v, p, iContinue);
				}
			}

			switch (eDest)
			{
				/* In this mode, write each query result to the key of the temporary
				** table iParm.
				*/
#if !SQLITE_OMIT_COMPOUND_SELECT
				case SRT_Union:
					{
						int r1;
						r1 = sqlite3GetTempReg(pParse);
						sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
						sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
						sqlite3ReleaseTempReg(pParse, r1);
						break;
					}

				/* Construct a record from the query result, but instead of
				** saving that record, use it as a key to delete elements from
				** the temporary table iParm.
				*/
				case SRT_Except:
					{
						sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nColumn);
						break;
					}
#endif

				/* Store the result as data using a unique key.
*/
				case SRT_Table:
				case SRT_EphemTab:
					{
						int r1 = sqlite3GetTempReg(pParse);
						testcase(eDest == SRT_Table);
						testcase(eDest == SRT_EphemTab);
						sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
						if (pOrderBy != null)
						{
							pushOntoSorter(pParse, pOrderBy, p, r1);
						}
						else
						{
							int r2 = sqlite3GetTempReg(pParse);
							sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
							sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
							sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
							sqlite3ReleaseTempReg(pParse, r2);
						}
						sqlite3ReleaseTempReg(pParse, r1);
						break;
					}

#if !SQLITE_OMIT_SUBQUERY
				/* If we are creating a set for an "expr IN (SELECT ...)" construct,
** then there should be a single item on the stack.  Write this
** item into the set table with bogus data.
*/
				case SRT_Set:
					{
						Debug.Assert(nColumn == 1);
						p.affinity = sqlite3CompareAffinity(pEList.a[0].pExpr, pDest.affinity);
						if (pOrderBy != null)
						{
							/* At first glance you would think we could optimize out the
							** ORDER BY in this case since the order of entries in the set
							** does not matter.  But there might be a LIMIT clause, in which
							** case the order does matter */
							pushOntoSorter(pParse, pOrderBy, p, regResult);
						}
						else
						{
							int r1 = sqlite3GetTempReg(pParse);
							sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, p.affinity, 1);
							sqlite3ExprCacheAffinityChange(pParse, regResult, 1);
							sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
							sqlite3ReleaseTempReg(pParse, r1);
						}
						break;
					}

				/* If any row exist in the result set, record that fact and abort.
				*/
				case SRT_Exists:
					{
						sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm);
						/* The LIMIT clause will terminate the loop for us */
						break;
					}

				/* If this is a scalar select that is part of an expression, then
				** store the results in the appropriate memory cell and break out
				** of the scan loop.
				*/
				case SRT_Mem:
					{
						Debug.Assert(nColumn == 1);
						if (pOrderBy != null)
						{
							pushOntoSorter(pParse, pOrderBy, p, regResult);
						}
						else
						{
							sqlite3ExprCodeMove(pParse, regResult, iParm, 1);
							/* The LIMIT clause will jump out of the loop for us */
						}
						break;
					}
#endif // * #if !SQLITE_OMIT_SUBQUERY */

				/* Send the data to the callback function or to a subroutine.  In the
** case of a subroutine, the subroutine itself is responsible for
** popping the data from the stack.
*/
				case SRT_Coroutine:
				case SRT_Output:
					{
						testcase(eDest == SRT_Coroutine);
						testcase(eDest == SRT_Output);
						if (pOrderBy != null)
						{
							int r1 = sqlite3GetTempReg(pParse);
							sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
							pushOntoSorter(pParse, pOrderBy, p, r1);
							sqlite3ReleaseTempReg(pParse, r1);
						}
						else if (eDest == SRT_Coroutine)
						{
							sqlite3VdbeAddOp1(v, OP_Yield, pDest.iParm);
						}
						else
						{
							sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn);
							sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn);
						}
						break;
					}

#if !SQLITE_OMIT_TRIGGER
				/* Discard the results.  This is used for SELECT statements inside
** the body of a TRIGGER.  The purpose of such selects is to call
** user-defined functions that have side effects.  We do not care
** about the actual results of the select.
*/
				default:
					{
						Debug.Assert(eDest == SRT_Discard);
						break;
					}
#endif
			}

			/* Jump to the end of the loop if the LIMIT is reached.  Except, if
			** there is a sorter, in which case the sorter has already limited
			** the output for us.
			*/
			if (pOrderBy == null && p.iLimit != 0)
			{
				sqlite3VdbeAddOp3(v, OP_IfZero, p.iLimit, iBreak, -1);
			}
		}

		/*
		** Given an expression list, generate a KeyInfo structure that records
		** the collating sequence for each expression in that expression list.
		**
		** If the ExprList is an ORDER BY or GROUP BY clause then the resulting
		** KeyInfo structure is appropriate for initializing a virtual index to
		** implement that clause.  If the ExprList is the result set of a SELECT
		** then the KeyInfo structure is appropriate for initializing a virtual
		** index to implement a DISTINCT test.
		**
		** Space to hold the KeyInfo structure is obtain from malloc.  The calling
		** function is responsible for seeing that this structure is eventually
		** freed.  Add the KeyInfo structure to the P4 field of an opcode using
		** P4_KEYINFO_HANDOFF is the usual way of dealing with this.
		*/

		private static KeyInfo keyInfoFromExprList(Parse pParse, ExprList pList)
		{
			sqlite3 db = pParse.db;
			int nExpr;
			KeyInfo pInfo;
			ExprList_item pItem;
			int i;

			nExpr = pList.nExpr;
			pInfo = new KeyInfo();//sqlite3DbMallocZero(db, sizeof(*pInfo) + nExpr*(CollSeq*.Length+1) );
			if (pInfo != null)
			{
				pInfo.aSortOrder = new byte[nExpr];// pInfo.aColl[nExpr];
				pInfo.aColl = new CollSeq[nExpr];
				pInfo.nField = (u16)nExpr;
				pInfo.enc = db.aDbStatic[0].pSchema.enc;// ENC(db);
				pInfo.db = db;
				for (i = 0; i < nExpr; i++)
				{//, pItem++){
					pItem = pList.a[i];
					CollSeq pColl;
					pColl = sqlite3ExprCollSeq(pParse, pItem.pExpr);
					if (pColl == null)
					{
						pColl = db.pDfltColl;
					}
					pInfo.aColl[i] = pColl;
					pInfo.aSortOrder[i] = (byte)pItem.sortOrder;
				}
			}
			return pInfo;
		}

#if !SQLITE_OMIT_COMPOUND_SELECT
		/*
** Name of the connection operator, used for error messages.
*/

		private static string selectOpName(int id)
		{
			string z;
			switch (id)
			{
				case TK_ALL:
					z = "UNION ALL";
					break;

				case TK_INTERSECT:
					z = "INTERSECT";
					break;

				case TK_EXCEPT:
					z = "EXCEPT";
					break;

				default:
					z = "UNION";
					break;
			}
			return z;
		}

#endif //* SQLITE_OMIT_COMPOUND_SELECT */

#if !SQLITE_OMIT_EXPLAIN
		/*
** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function
** is a no-op. Otherwise, it adds a single row of output to the EQP result,
** where the caption is of the form:
**
**   "USE TEMP B-TREE FOR xxx"
**
** where xxx is one of "DISTINCT", "ORDER BY" or "GROUP BY". Exactly which
** is determined by the zUsage argument.
*/

		private static void explainTempTable(Parse pParse, string zUsage)
		{
			if (pParse.explain == 2)
			{
				Vdbe v = pParse.pVdbe;
				string zMsg = sqlite3MPrintf(pParse.db, "USE TEMP B-TREE FOR %s", zUsage);
				sqlite3VdbeAddOp4(v, OP_Explain, pParse.iSelectId, 0, 0, zMsg, P4_DYNAMIC);
			}
		}

		/*
		** Assign expression b to lvalue a. A second, no-op, version of this macro
		** is provided when SQLITE_OMIT_EXPLAIN is defined. This allows the code
		** in sqlite3Select() to assign values to structure member variables that
		** only exist if SQLITE_OMIT_EXPLAIN is not defined without polluting the
		** code with #if !directives.
		*/

		//# define explainSetInteger(a, b) a = b
		private static void explainSetInteger(ref int a, int b)
		{
			a = b;
		}

		private static void explainSetInteger(ref byte a, int b)
		{
			a = (byte)b;
		}

#else
/* No-op versions of the explainXXX() functions and macros. */
//# define explainTempTable(y,z)
static void explainTempTable(ref int a, int b){ a = b;}

//# define explainSetInteger(y,z)
static void explainSetInteger(ref int a, int b){ a = b;}
#endif

#if !(SQLITE_OMIT_EXPLAIN) && !(SQLITE_OMIT_COMPOUND_SELECT)
		/*
    ** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function
    ** is a no-op. Otherwise, it adds a single row of output to the EQP result,
    ** where the caption is of one of the two forms:
    **
    **   "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)"
    **   "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)"
    **
    ** where iSub1 and iSub2 are the integers passed as the corresponding
    ** function parameters, and op is the text representation of the parameter
    ** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT,
    ** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is
    ** false, or the second form if it is true.
    */

		private static void explainComposite(
		Parse pParse,                   /* Parse context */
		int op,                         /* One of TK_UNION, TK_EXCEPT etc. */
		int iSub1,                      /* Subquery id 1 */
		int iSub2,                      /* Subquery id 2 */
		bool bUseTmp                     /* True if a temp table was used */
		)
		{
			Debug.Assert(op == TK_UNION || op == TK_EXCEPT || op == TK_INTERSECT || op == TK_ALL);
			if (pParse.explain == 2)
			{
				Vdbe v = pParse.pVdbe;
				string zMsg = sqlite3MPrintf(
				pParse.db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2,
				bUseTmp ? "USING TEMP B-TREE " : "", selectOpName(op)
				);
				sqlite3VdbeAddOp4(v, OP_Explain, pParse.iSelectId, 0, 0, zMsg, P4_DYNAMIC);
			}
		}

#else
/* No-op versions of the explainXXX() functions and macros. */
//# define explainComposite(v,w,x,y,z)
static void explainComposite(Parse v, int w,int x,int y,bool z) {}
#endif

		/*
** If the inner loop was generated using a non-null pOrderBy argument,
** then the results were placed in a sorter.  After the loop is terminated
** we need to run the sorter and output the results.  The following
** routine generates the code needed to do that.
*/

		private static void generateSortTail(
		Parse pParse,     /* Parsing context */
		Select p,         /* The SELECT statement */
		Vdbe v,           /* Generate code into this VDBE */
		int nColumn,      /* Number of columns of data */
		SelectDest pDest  /* Write the sorted results here */
		)
		{
			int addrBreak = sqlite3VdbeMakeLabel(v);    /* Jump here to exit loop */
			int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */
			int addr;
			int iTab;
			int pseudoTab = 0;
			ExprList pOrderBy = p.pOrderBy;

			int eDest = pDest.eDest;
			int iParm = pDest.iParm;

			int regRow;
			int regRowid;

			iTab = pOrderBy.iECursor;
			regRow = sqlite3GetTempReg(pParse);
			if (eDest == SRT_Output || eDest == SRT_Coroutine)
			{
				pseudoTab = pParse.nTab++;
				sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn);
				regRowid = 0;
			}
			else
			{
				regRowid = sqlite3GetTempReg(pParse);
			}
			addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
			codeOffset(v, p, addrContinue);
			sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy.nExpr + 1, regRow);
			switch (eDest)
			{
				case SRT_Table:
				case SRT_EphemTab:
					{
						testcase(eDest == SRT_Table);
						testcase(eDest == SRT_EphemTab);
						sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
						sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);
						sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
						break;
					}
#if !SQLITE_OMIT_SUBQUERY
				case SRT_Set:
					{
						Debug.Assert(nColumn == 1);
						sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, p.affinity, 1);
						sqlite3ExprCacheAffinityChange(pParse, regRow, 1);
						sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
						break;
					}
				case SRT_Mem:
					{
						Debug.Assert(nColumn == 1);
						sqlite3ExprCodeMove(pParse, regRow, iParm, 1);
						/* The LIMIT clause will terminate the loop for us */
						break;
					}
#endif
				default:
					{
						int i;
						Debug.Assert(eDest == SRT_Output || eDest == SRT_Coroutine);
						testcase(eDest == SRT_Output);
						testcase(eDest == SRT_Coroutine);
						for (i = 0; i < nColumn; i++)
						{
							Debug.Assert(regRow != pDest.iMem + i);
							sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest.iMem + i);
							if (i == 0)
							{
								sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
							}
						}
						if (eDest == SRT_Output)
						{
							sqlite3VdbeAddOp2(v, OP_ResultRow, pDest.iMem, nColumn);
							sqlite3ExprCacheAffinityChange(pParse, pDest.iMem, nColumn);
						}
						else
						{
							sqlite3VdbeAddOp1(v, OP_Yield, pDest.iParm);
						}
						break;
					}
			}
			sqlite3ReleaseTempReg(pParse, regRow);
			sqlite3ReleaseTempReg(pParse, regRowid);

			/* The bottom of the loop
			*/
			sqlite3VdbeResolveLabel(v, addrContinue);
			sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
			sqlite3VdbeResolveLabel(v, addrBreak);
			if (eDest == SRT_Output || eDest == SRT_Coroutine)
			{
				sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
			}
		}

		/*
		** Return a pointer to a string containing the 'declaration type' of the
		** expression pExpr. The string may be treated as static by the caller.
		**
		** The declaration type is the exact datatype definition extracted from the
		** original CREATE TABLE statement if the expression is a column. The
		** declaration type for a ROWID field is INTEGER. Exactly when an expression
		** is considered a column can be complex in the presence of subqueries. The
		** result-set expression in all of the following SELECT statements is
		** considered a column by this function.
		**
		**   SELECT col FROM tbl;
		**   SELECT (SELECT col FROM tbl;
		**   SELECT (SELECT col FROM tbl);
		**   SELECT abc FROM (SELECT col AS abc FROM tbl);
		**
		** The declaration type for any expression other than a column is NULL.
		*/

		private static string columnType(
		NameContext pNC,
		Expr pExpr,
		ref string pzOriginDb,
		ref string pzOriginTab,
		ref string pzOriginCol
		)
		{
			string zType = null;
			string zOriginDb = null;
			string zOriginTab = null;
			string zOriginCol = null;
			int j;
			if (NEVER(pExpr == null) || pNC.pSrcList == null)
				return null;

			switch (pExpr.op)
			{
				case TK_AGG_COLUMN:
				case TK_COLUMN:
					{
						/* The expression is a column. Locate the table the column is being
						** extracted from in NameContext.pSrcList. This table may be real
						** database table or a subquery.
						*/
						Table pTab = null;            /* Table structure column is extracted from */
						Select pS = null;            /* Select the column is extracted from */
						int iCol = pExpr.iColumn;  /* Index of column in pTab */
						testcase(pExpr.op == TK_AGG_COLUMN);
						testcase(pExpr.op == TK_COLUMN);
						while (pNC != null && pTab == null)
						{
							SrcList pTabList = pNC.pSrcList;
							for (j = 0; j < pTabList.nSrc && pTabList.a[j].iCursor != pExpr.iTable; j++)
								;
							if (j < pTabList.nSrc)
							{
								pTab = pTabList.a[j].pTab;
								pS = pTabList.a[j].pSelect;
							}
							else
							{
								pNC = pNC.pNext;
							}
						}

						if (pTab == null)
						{
							/* At one time, code such as "SELECT new.x" within a trigger would
							** cause this condition to run.  Since then, we have restructured how
							** trigger code is generated and so this condition is no longer
							** possible. However, it can still be true for statements like
							** the following:
							**
							**   CREATE TABLE t1(col INTEGER);
							**   SELECT (SELECT t1.col) FROM FROM t1;
							**
							** when columnType() is called on the expression "t1.col" in the
							** sub-select. In this case, set the column type to NULL, even
							** though it should really be "INTEGER".
							**
							** This is not a problem, as the column type of "t1.col" is never
							** used. When columnType() is called on the expression
							** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT
							** branch below.  */
							break;
						}

						//Debug.Assert( pTab != null && pExpr.pTab == pTab );
						if (pS != null)
						{
							/* The "table" is actually a sub-select or a view in the FROM clause
							** of the SELECT statement. Return the declaration type and origin
							** data for the result-set column of the sub-select.
							*/
							if (iCol >= 0 && ALWAYS(iCol < pS.pEList.nExpr))
							{
								/* If iCol is less than zero, then the expression requests the
								** rowid of the sub-select or view. This expression is legal (see
								** test case misc2.2.2) - it always evaluates to NULL.
								*/
								NameContext sNC = new NameContext();
								Expr p = pS.pEList.a[iCol].pExpr;
								sNC.pSrcList = pS.pSrc;
								sNC.pNext = pNC;
								sNC.pParse = pNC.pParse;
								zType = columnType(sNC, p, ref zOriginDb, ref zOriginTab, ref zOriginCol);
							}
						}
						else if (ALWAYS(pTab.pSchema))
						{
							/* A real table */
							Debug.Assert(pS == null);
							if (iCol < 0)
								iCol = pTab.iPKey;
							Debug.Assert(iCol == -1 || (iCol >= 0 && iCol < pTab.nCol));
							if (iCol < 0)
							{
								zType = "INTEGER";
								zOriginCol = "rowid";
							}
							else
							{
								zType = pTab.aCol[iCol].zType;
								zOriginCol = pTab.aCol[iCol].zName;
							}
							zOriginTab = pTab.zName;
							if (pNC.pParse != null)
							{
								int iDb = sqlite3SchemaToIndex(pNC.pParse.db, pTab.pSchema);
								zOriginDb = pNC.pParse.db.aDb[iDb].zName;
							}
						}
						break;
					}
#if !SQLITE_OMIT_SUBQUERY
				case TK_SELECT:
					{
						/* The expression is a sub-select. Return the declaration type and
						** origin info for the single column in the result set of the SELECT
						** statement.
						*/
						NameContext sNC = new NameContext();
						Select pS = pExpr.x.pSelect;
						Expr p = pS.pEList.a[0].pExpr;
						Debug.Assert(ExprHasProperty(pExpr, EP_xIsSelect));
						sNC.pSrcList = pS.pSrc;
						sNC.pNext = pNC;
						sNC.pParse = pNC.pParse;
						zType = columnType(sNC, p, ref zOriginDb, ref zOriginTab, ref zOriginCol);
						break;
					}
#endif
			}

			//if ( pzOriginDb != null )
			{
				//Debug.Assert( pzOriginTab != null && pzOriginCol != null );
				pzOriginDb = zOriginDb;
				pzOriginTab = zOriginTab;
				pzOriginCol = zOriginCol;
			}
			return zType;
		}

		/*
		** Generate code that will tell the VDBE the declaration types of columns
		** in the result set.
		*/

		private static void generateColumnTypes(
		Parse pParse,      /* Parser context */
		SrcList pTabList,  /* List of tables */
		ExprList pEList    /* Expressions defining the result set */
		)
		{
#if !SQLITE_OMIT_DECLTYPE
			Vdbe v = pParse.pVdbe;
			int i;
			NameContext sNC = new NameContext();
			sNC.pSrcList = pTabList;
			sNC.pParse = pParse;
			for (i = 0; i < pEList.nExpr; i++)
			{
				Expr p = pEList.a[i].pExpr;
				string zType;
#if SQLITE_ENABLE_COLUMN_METADATA
        string zOrigDb = null;
        string zOrigTab = null;
        string zOrigCol = null;
        zType = columnType( sNC, p, ref zOrigDb, ref zOrigTab, ref zOrigCol );

        /* The vdbe must make its own copy of the column-type and other
        ** column specific strings, in case the schema is reset before this
        ** virtual machine is deleted.
        */
        sqlite3VdbeSetColName( v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT );
        sqlite3VdbeSetColName( v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT );
        sqlite3VdbeSetColName( v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT );
#else
				string sDummy = null;
				zType = columnType(sNC, p, ref sDummy, ref sDummy, ref sDummy);
#endif
				sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
			}
#endif //* SQLITE_OMIT_DECLTYPE */
		}

		/*
		** Generate code that will tell the VDBE the names of columns
		** in the result set.  This information is used to provide the
		** azCol[] values in the callback.
		*/

		private static void generateColumnNames(
		Parse pParse,      /* Parser context */
		SrcList pTabList,  /* List of tables */
		ExprList pEList    /* Expressions defining the result set */
		)
		{
			Vdbe v = pParse.pVdbe;
			int i, j;
			sqlite3 db = pParse.db;
			bool fullNames;
			bool shortNames;

#if !SQLITE_OMIT_EXPLAIN
			/* If this is an EXPLAIN, skip this step */
			if (pParse.explain != 0)
			{
				return;
			}
#endif

			if (pParse.colNamesSet != 0 || NEVER(v == null) /*|| db.mallocFailed != 0 */ )
				return;
			pParse.colNamesSet = 1;
			fullNames = (db.flags & SQLITE_FullColNames) != 0;
			shortNames = (db.flags & SQLITE_ShortColNames) != 0;
			sqlite3VdbeSetNumCols(v, pEList.nExpr);
			for (i = 0; i < pEList.nExpr; i++)
			{
				Expr p;
				p = pEList.a[i].pExpr;
				if (NEVER(p == null))
					continue;
				if (pEList.a[i].zName != null)
				{
					string zName = pEList.a[i].zName;
					sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
				}
				else if ((p.op == TK_COLUMN || p.op == TK_AGG_COLUMN) && pTabList != null)
				{
					Table pTab;
					string zCol;
					int iCol = p.iColumn;
					for (j = 0; ALWAYS(j < pTabList.nSrc); j++)
					{
						if (pTabList.a[j].iCursor == p.iTable)
							break;
					}
					Debug.Assert(j < pTabList.nSrc);
					pTab = pTabList.a[j].pTab;
					if (iCol < 0)
						iCol = pTab.iPKey;
					Debug.Assert(iCol == -1 || (iCol >= 0 && iCol < pTab.nCol));
					if (iCol < 0)
					{
						zCol = "rowid";
					}
					else
					{
						zCol = pTab.aCol[iCol].zName;
					}
					if (!shortNames && !fullNames)
					{
						sqlite3VdbeSetColName(v, i, COLNAME_NAME,
						pEList.a[i].zSpan, SQLITE_DYNAMIC);//sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
					}
					else if (fullNames)
					{
						string zName;
						zName = sqlite3MPrintf(db, "%s.%s", pTab.zName, zCol);
						sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC);
					}
					else
					{
						sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
					}
				}
				else
				{
					sqlite3VdbeSetColName(v, i, COLNAME_NAME,
					pEList.a[i].zSpan, SQLITE_DYNAMIC);//sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
				}
			}
			generateColumnTypes(pParse, pTabList, pEList);
		}

		/*
		** Given a an expression list (which is really the list of expressions
		** that form the result set of a SELECT statement) compute appropriate
		** column names for a table that would hold the expression list.
		**
		** All column names will be unique.
		**
		** Only the column names are computed.  Column.zType, Column.zColl,
		** and other fields of Column are zeroed.
		**
		** Return SQLITE_OK on success.  If a memory allocation error occurs,
		** store NULL in paCol and 0 in pnCol and return SQLITE_NOMEM.
		*/

		private static int selectColumnsFromExprList(
		Parse pParse,          /* Parsing context */
		ExprList pEList,       /* Expr list from which to derive column names */
		ref int pnCol,             /* Write the number of columns here */
		ref Column[] paCol          /* Write the new column list here */
		)
		{
			sqlite3 db = pParse.db;     /* Database connection */
			int i, j;                   /* Loop counters */
			int cnt;                    /* Index added to make the name unique */
			Column[] aCol;
			Column pCol; /* For looping over result columns */
			int nCol;                   /* Number of columns in the result set */
			Expr p;                     /* Expression for a single result column */
			string zName;               /* Column name */
			int nName;                  /* Size of name in zName[] */

			pnCol = nCol = pEList.nExpr;
			aCol = paCol = new Column[nCol];//sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
			//if ( aCol == null )
			//  return SQLITE_NOMEM;
			for (i = 0; i < nCol; i++)//, pCol++)
			{
				if (aCol[i] == null)
					aCol[i] = new Column();
				pCol = aCol[i];
				/* Get an appropriate name for the column
				*/
				p = pEList.a[i].pExpr;
				Debug.Assert(p.pRight == null || ExprHasProperty(p.pRight, EP_IntValue)
				|| p.pRight.u.zToken == null || p.pRight.u.zToken.Length > 0);
				if (pEList.a[i].zName != null && (zName = pEList.a[i].zName) != "")
				{
					/* If the column contains an "AS <name>" phrase, use <name> as the name */
					//zName = sqlite3DbStrDup(db, zName);
				}
				else
				{
					Expr pColExpr = p;      /* The expression that is the result column name */
					Table pTab;             /* Table associated with this expression */
					while (pColExpr.op == TK_DOT)
						pColExpr = pColExpr.pRight;
					if (pColExpr.op == TK_COLUMN && ALWAYS(pColExpr.pTab != null))
					{
						/* For columns use the column name name */
						int iCol = pColExpr.iColumn;
						pTab = pColExpr.pTab;
						if (iCol < 0)
							iCol = pTab.iPKey;
						zName = sqlite3MPrintf(db, "%s",
						iCol >= 0 ? pTab.aCol[iCol].zName : "rowid");
					}
					else if (pColExpr.op == TK_ID)
					{
						Debug.Assert(!ExprHasProperty(pColExpr, EP_IntValue));
						zName = sqlite3MPrintf(db, "%s", pColExpr.u.zToken);
					}
					else
					{
						/* Use the original text of the column expression as its name */
						zName = sqlite3MPrintf(db, "%s", pEList.a[i].zSpan);
					}
				}
				//if ( db.mallocFailed != 0 )
				//{
				//  sqlite3DbFree( db, ref zName );
				//  break;
				//}

				/* Make sure the column name is unique.  If the name is not unique,
				** append a integer to the name so that it becomes unique.
				*/
				nName = sqlite3Strlen30(zName);
				for (j = cnt = 0; j < i; j++)
				{
					if (aCol[j].zName.Equals(zName, StringComparison.OrdinalIgnoreCase))
					{
						string zNewName;
						//zName[nName] = 0;
						zNewName = sqlite3MPrintf(db, "%s:%d", zName.Substring(0, nName), ++cnt);
						sqlite3DbFree(db, ref zName);
						zName = zNewName;
						j = -1;
						if (zName == "")
							break;
					}
				}
				pCol.zName = zName;
			}
			//if ( db.mallocFailed != 0 )
			//{
			//  for ( j = 0 ; j < i ; j++ )
			//  {
			//    sqlite3DbFree( db, aCol[j].zName );
			//  }
			//  sqlite3DbFree( db, aCol );
			//  paCol = null;
			//  pnCol = 0;
			//  return SQLITE_NOMEM;
			//}
			return SQLITE_OK;
		}

		/*
		** Add type and collation information to a column list based on
		** a SELECT statement.
		**
		** The column list presumably came from selectColumnNamesFromExprList().
		** The column list has only names, not types or collations.  This
		** routine goes through and adds the types and collations.
		**
		** This routine requires that all identifiers in the SELECT
		** statement be resolved.
		*/

		private static void selectAddColumnTypeAndCollation(
		Parse pParse,         /* Parsing contexts */
		int nCol,             /* Number of columns */
		Column[] aCol,        /* List of columns */
		Select pSelect        /* SELECT used to determine types and collations */
		)
		{
			//sqlite3 db = pParse.db;
			NameContext sNC;
			Column pCol;
			CollSeq pColl;
			int i;
			Expr p;
			ExprList_item[] a;

			Debug.Assert(pSelect != null);
			Debug.Assert((pSelect.selFlags & SF_Resolved) != 0);
			Debug.Assert(nCol == pSelect.pEList.nExpr /*|| db.mallocFailed != 0 */ );
			//      if ( db.mallocFailed != 0 ) return;
			sNC = new NameContext();// memset( &sNC, 0, sizeof( sNC ) );
			sNC.pSrcList = pSelect.pSrc;
			a = pSelect.pEList.a;
			for (i = 0; i < nCol; i++)//, pCol++ )
			{
				pCol = aCol[i];
				p = a[i].pExpr;
				string bDummy = null;
				pCol.zType = columnType(sNC, p, ref bDummy, ref bDummy, ref bDummy);// sqlite3DbStrDup( db, columnType( sNC, p, 0, 0, 0 ) );
				pCol.affinity = sqlite3ExprAffinity(p);
				if (pCol.affinity == 0)
					pCol.affinity = SQLITE_AFF_NONE;
				pColl = sqlite3ExprCollSeq(pParse, p);
				if (pColl != null)
				{
					pCol.zColl = pColl.zName;// sqlite3DbStrDup( db, pColl.zName );
				}
			}
		}

		/*
		** Given a SELECT statement, generate a Table structure that describes
		** the result set of that SELECT.
		*/

		private static Table sqlite3ResultSetOfSelect(Parse pParse, Select pSelect)
		{
			Table pTab;
			sqlite3 db = pParse.db;
			int savedFlags;

			savedFlags = db.flags;
			db.flags &= ~SQLITE_FullColNames;
			db.flags |= SQLITE_ShortColNames;
			sqlite3SelectPrep(pParse, pSelect, null);
			if (pParse.nErr != 0)
				return null;
			while (pSelect.pPrior != null)
				pSelect = pSelect.pPrior;
			db.flags = savedFlags;
			pTab = new Table();// sqlite3DbMallocZero( db, sizeof( Table ) );
			if (pTab == null)
			{
				return null;
			}
			/* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
			** is disabled */
			Debug.Assert(db.lookaside.bEnabled == 0);
			pTab.nRef = 1;
			pTab.zName = null;
			pTab.nRowEst = 1000000;
			selectColumnsFromExprList(pParse, pSelect.pEList, ref pTab.nCol, ref pTab.aCol);
			selectAddColumnTypeAndCollation(pParse, pTab.nCol, pTab.aCol, pSelect);
			pTab.iPKey = -1;
			//if ( db.mallocFailed != 0 )
			//{
			//  sqlite3DeleteTable(db, ref pTab );
			//  return null;
			//}
			return pTab;
		}

		/*
		** Get a VDBE for the given parser context.  Create a new one if necessary.
		** If an error occurs, return NULL and leave a message in pParse.
		*/

		private static Vdbe sqlite3GetVdbe(Parse pParse)
		{
			Vdbe v = pParse.pVdbe;
			if (v == null)
			{
				v = pParse.pVdbe = sqlite3VdbeCreate(pParse.db);
#if !SQLITE_OMIT_TRACE
				if (v != null)
				{
					sqlite3VdbeAddOp0(v, OP_Trace);
				}
#endif
			}
			return v;
		}

		/*
		** Compute the iLimit and iOffset fields of the SELECT based on the
		** pLimit and pOffset expressions.  pLimit and pOffset hold the expressions
		** that appear in the original SQL statement after the LIMIT and OFFSET
		** keywords.  Or NULL if those keywords are omitted. iLimit and iOffset
		** are the integer memory register numbers for counters used to compute
		** the limit and offset.  If there is no limit and/or offset, then
		** iLimit and iOffset are negative.
		**
		** This routine changes the values of iLimit and iOffset only if
		** a limit or offset is defined by pLimit and pOffset.  iLimit and
		** iOffset should have been preset to appropriate default values
		** (usually but not always -1) prior to calling this routine.
		** Only if pLimit!=0 or pOffset!=0 do the limit registers get
		** redefined.  The UNION ALL operator uses this property to force
		** the reuse of the same limit and offset registers across multiple
		** SELECT statements.
		*/

		private static void computeLimitRegisters(Parse pParse, Select p, int iBreak)
		{
			Vdbe v = null;
			int iLimit = 0;
			int iOffset;
			int addr1, n = 0;
			if (p.iLimit != 0)
				return;

			/*
			** "LIMIT -1" always shows all rows.  There is some
			** contraversy about what the correct behavior should be.
			** The current implementation interprets "LIMIT 0" to mean
			** no rows.
			*/
			sqlite3ExprCacheClear(pParse);
			Debug.Assert(p.pOffset == null || p.pLimit != null);
			if (p.pLimit != null)
			{
				p.iLimit = iLimit = ++pParse.nMem;
				v = sqlite3GetVdbe(pParse);
				if (NEVER(v == null))
					return;  /* VDBE should have already been allocated */
				if (sqlite3ExprIsInteger(p.pLimit, ref n) != 0)
				{
					sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
					VdbeComment(v, "LIMIT counter");
					if (n == 0)
					{
						sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
					}
					else
					{
						if (p.nSelectRow > (double)n)
							p.nSelectRow = (double)n;
					}
				}
				else
				{
					sqlite3ExprCode(pParse, p.pLimit, iLimit);
					sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit);
#if SQLITE_DEBUG
					VdbeComment(v, "LIMIT counter");
#endif
					sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak);
				}
				if (p.pOffset != null)
				{
					p.iOffset = iOffset = ++pParse.nMem;
					pParse.nMem++;   /* Allocate an extra register for limit+offset */
					sqlite3ExprCode(pParse, p.pOffset, iOffset);
					sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset);
#if SQLITE_DEBUG
					VdbeComment(v, "OFFSET counter");
#endif
					addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset);
					sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset);
					sqlite3VdbeJumpHere(v, addr1);
					sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset + 1);
#if SQLITE_DEBUG
					VdbeComment(v, "LIMIT+OFFSET");
#endif
					addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit);
					sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset + 1);
					sqlite3VdbeJumpHere(v, addr1);
				}
			}
		}

#if !SQLITE_OMIT_COMPOUND_SELECT
		/*
** Return the appropriate collating sequence for the iCol-th column of
** the result set for the compound-select statement "p".  Return NULL if
** the column has no default collating sequence.
**
** The collating sequence for the compound select is taken from the
** left-most term of the select that has a collating sequence.
*/

		private static CollSeq multiSelectCollSeq(Parse pParse, Select p, int iCol)
		{
			CollSeq pRet;
			if (p.pPrior != null)
			{
				pRet = multiSelectCollSeq(pParse, p.pPrior, iCol);
			}
			else
			{
				pRet = null;
			}
			Debug.Assert(iCol >= 0);
			if (pRet == null && iCol < p.pEList.nExpr)
			{
				pRet = sqlite3ExprCollSeq(pParse, p.pEList.a[iCol].pExpr);
			}
			return pRet;
		}

#endif // * SQLITE_OMIT_COMPOUND_SELECT */

		/* Forward reference */
		//static int multiSelectOrderBy(
		//  Parse* pParse,        /* Parsing context */
		//  Select* p,            /* The right-most of SELECTs to be coded */
		//  SelectDest* pDest     /* What to do with query results */
		//);

#if !SQLITE_OMIT_COMPOUND_SELECT
		/*
** This routine is called to process a compound query form from
** two or more separate queries using UNION, UNION ALL, EXCEPT, or
** INTERSECT
**
** "p" points to the right-most of the two queries.  the query on the
** left is p.pPrior.  The left query could also be a compound query
** in which case this routine will be called recursively.
**
** The results of the total query are to be written into a destination
** of type eDest with parameter iParm.
**
** Example 1:  Consider a three-way compound SQL statement.
**
**     SELECT a FROM t1 UNION SELECT b FROM t2 UNION SELECT c FROM t3
**
** This statement is parsed up as follows:
**
**     SELECT c FROM t3
**      |
**      `----.  SELECT b FROM t2
**                |
**                `-----.  SELECT a FROM t1
**
** The arrows in the diagram above represent the Select.pPrior pointer.
** So if this routine is called with p equal to the t3 query, then
** pPrior will be the t2 query.  p.op will be TK_UNION in this case.
**
** Notice that because of the way SQLite parses compound SELECTs, the
** individual selects always group from left to right.
*/

		private static int multiSelect(
		Parse pParse,             /* Parsing context */
		Select p,                 /* The right-most of SELECTs to be coded */
		SelectDest pDest          /* What to do with query results */
		)
		{
			int rc = SQLITE_OK;       /* Success code from a subroutine */
			Select pPrior;            /* Another SELECT immediately to our left */
			Vdbe v;                   /* Generate code to this VDBE */
			SelectDest dest = new SelectDest(); /* Alternative data destination */
			Select pDelete = null;    /* Chain of simple selects to delete */
			sqlite3 db;               /* Database connection */
#if !SQLITE_OMIT_EXPLAIN
			int iSub1 = 0;            /* EQP id of left-hand query */
			int iSub2 = 0;            /* EQP id of right-hand query */
#endif

			/* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs.  Only
** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
*/
			Debug.Assert(p != null && p.pPrior != null);  /* Calling function guarantees this much */
			db = pParse.db;
			pPrior = p.pPrior;
			Debug.Assert(pPrior.pRightmost != pPrior);
			Debug.Assert(pPrior.pRightmost == p.pRightmost);
			dest = pDest;
			if (pPrior.pOrderBy != null)
			{
				sqlite3ErrorMsg(pParse, "ORDER BY clause should come after %s not before",
				selectOpName(p.op));
				rc = 1;
				goto multi_select_end;
			}
			if (pPrior.pLimit != null)
			{
				sqlite3ErrorMsg(pParse, "LIMIT clause should come after %s not before",
				selectOpName(p.op));
				rc = 1;
				goto multi_select_end;
			}

			v = sqlite3GetVdbe(pParse);
			Debug.Assert(v != null);  /* The VDBE already created by calling function */

			/* Create the destination temporary table if necessary
			*/
			if (dest.eDest == SRT_EphemTab)
			{
				Debug.Assert(p.pEList != null);
				sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iParm, p.pEList.nExpr);
				sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
				dest.eDest = SRT_Table;
			}

			/* Make sure all SELECTs in the statement have the same number of elements
			** in their result sets.
			*/
			Debug.Assert(p.pEList != null && pPrior.pEList != null);
			if (p.pEList.nExpr != pPrior.pEList.nExpr)
			{
				sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" +
				" do not have the same number of result columns", selectOpName(p.op));
				rc = 1;
				goto multi_select_end;
			}

			/* Compound SELECTs that have an ORDER BY clause are handled separately.
			*/
			if (p.pOrderBy != null)
			{
				return multiSelectOrderBy(pParse, p, pDest);
			}

			/* Generate code for the left and right SELECT statements.
			*/
			switch (p.op)
			{
				case TK_ALL:
					{
						int addr = 0;
						int nLimit = 0;
						Debug.Assert(pPrior.pLimit == null);
						pPrior.pLimit = p.pLimit;
						pPrior.pOffset = p.pOffset;
						explainSetInteger(ref iSub1, pParse.iNextSelectId);
						rc = sqlite3Select(pParse, pPrior, ref dest);
						p.pLimit = null;
						p.pOffset = null;
						if (rc != 0)
						{
							goto multi_select_end;
						}
						p.pPrior = null;
						p.iLimit = pPrior.iLimit;
						p.iOffset = pPrior.iOffset;
						if (p.iLimit != 0)
						{
							addr = sqlite3VdbeAddOp1(v, OP_IfZero, p.iLimit);
#if SQLITE_DEBUG
							VdbeComment(v, "Jump ahead if LIMIT reached");
#endif
						}
						explainSetInteger(ref iSub2, pParse.iNextSelectId);
						rc = sqlite3Select(pParse, p, ref dest);
						testcase(rc != SQLITE_OK);
						pDelete = p.pPrior;
						p.pPrior = pPrior;
						p.nSelectRow += pPrior.nSelectRow;
						if (pPrior.pLimit != null
						 && sqlite3ExprIsInteger(pPrior.pLimit, ref nLimit) != 0
						 && p.nSelectRow > (double)nLimit
						)
						{
							p.nSelectRow = (double)nLimit;
						}
						if (addr != 0)
						{
							sqlite3VdbeJumpHere(v, addr);
						}
						break;
					}
				case TK_EXCEPT:
				case TK_UNION:
					{
						int unionTab;    /* VdbeCursor number of the temporary table holding result */
						u8 op = 0;      /* One of the SRT_ operations to apply to self */
						int priorOp;     /* The SRT_ operation to apply to prior selects */
						Expr pLimit, pOffset; /* Saved values of p.nLimit and p.nOffset */
						int addr;
						SelectDest uniondest = new SelectDest();

						testcase(p.op == TK_EXCEPT);
						testcase(p.op == TK_UNION);
						priorOp = SRT_Union;
						if (dest.eDest == priorOp && ALWAYS(null == p.pLimit && null == p.pOffset))
						{
							/* We can reuse a temporary table generated by a SELECT to our
							** right.
							*/
							Debug.Assert(p.pRightmost != p);  /* Can only happen for leftward elements
** of a 3-way or more compound */
							Debug.Assert(p.pLimit == null);      /* Not allowed on leftward elements */
							Debug.Assert(p.pOffset == null);     /* Not allowed on leftward elements */
							unionTab = dest.iParm;
						}
						else
						{
							/* We will need to create our own temporary table to hold the
							** intermediate results.
							*/
							unionTab = pParse.nTab++;
							Debug.Assert(p.pOrderBy == null);
							addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
							Debug.Assert(p.addrOpenEphm[0] == -1);
							p.addrOpenEphm[0] = addr;
							p.pRightmost.selFlags |= SF_UsesEphemeral;
							Debug.Assert(p.pEList != null);
						}

						/* Code the SELECT statements to our left
						*/
						Debug.Assert(pPrior.pOrderBy == null);
						sqlite3SelectDestInit(uniondest, priorOp, unionTab);
						explainSetInteger(ref iSub1, pParse.iNextSelectId);
						rc = sqlite3Select(pParse, pPrior, ref uniondest);
						if (rc != 0)
						{
							goto multi_select_end;
						}

						/* Code the current SELECT statement
						*/
						if (p.op == TK_EXCEPT)
						{
							op = SRT_Except;
						}
						else
						{
							Debug.Assert(p.op == TK_UNION);
							op = SRT_Union;
						}
						p.pPrior = null;
						pLimit = p.pLimit;
						p.pLimit = null;
						pOffset = p.pOffset;
						p.pOffset = null;
						uniondest.eDest = op;
						explainSetInteger(ref iSub2, pParse.iNextSelectId);
						rc = sqlite3Select(pParse, p, ref uniondest);
						testcase(rc != SQLITE_OK);
						/* Query flattening in sqlite3Select() might refill p.pOrderBy.
						** Be sure to delete p.pOrderBy, therefore, to avoid a memory leak. */
						sqlite3ExprListDelete(db, ref p.pOrderBy);
						pDelete = p.pPrior;
						p.pPrior = pPrior;
						p.pOrderBy = null;
						if (p.op == TK_UNION)
							p.nSelectRow += pPrior.nSelectRow;
						sqlite3ExprDelete(db, ref p.pLimit);
						p.pLimit = pLimit;
						p.pOffset = pOffset;
						p.iLimit = 0;
						p.iOffset = 0;

						/* Convert the data in the temporary table into whatever form
						** it is that we currently need.
						*/
						Debug.Assert(unionTab == dest.iParm || dest.eDest != priorOp);
						if (dest.eDest != priorOp)
						{
							int iCont, iBreak, iStart;
							Debug.Assert(p.pEList != null);
							if (dest.eDest == SRT_Output)
							{
								Select pFirst = p;
								while (pFirst.pPrior != null)
									pFirst = pFirst.pPrior;
								generateColumnNames(pParse, null, pFirst.pEList);
							}
							iBreak = sqlite3VdbeMakeLabel(v);
							iCont = sqlite3VdbeMakeLabel(v);
							computeLimitRegisters(pParse, p, iBreak);
							sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak);
							iStart = sqlite3VdbeCurrentAddr(v);
							selectInnerLoop(pParse, p, p.pEList, unionTab, p.pEList.nExpr,
							null, -1, dest, iCont, iBreak);
							sqlite3VdbeResolveLabel(v, iCont);
							sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart);
							sqlite3VdbeResolveLabel(v, iBreak);
							sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0);
						}
						break;
					}
				default:
					Debug.Assert(p.op == TK_INTERSECT);
					{
						int tab1, tab2;
						int iCont, iBreak, iStart;
						Expr pLimit, pOffset;
						int addr;
						SelectDest intersectdest = new SelectDest();
						int r1;

						/* INTERSECT is different from the others since it requires
						** two temporary tables.  Hence it has its own case.  Begin
						** by allocating the tables we will need.
						*/
						tab1 = pParse.nTab++;
						tab2 = pParse.nTab++;
						Debug.Assert(p.pOrderBy == null);

						addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
						Debug.Assert(p.addrOpenEphm[0] == -1);
						p.addrOpenEphm[0] = addr;
						p.pRightmost.selFlags |= SF_UsesEphemeral;
						Debug.Assert(p.pEList != null);

						/* Code the SELECTs to our left into temporary table "tab1".
						*/
						sqlite3SelectDestInit(intersectdest, SRT_Union, tab1);
						explainSetInteger(ref iSub1, pParse.iNextSelectId);
						rc = sqlite3Select(pParse, pPrior, ref intersectdest);
						if (rc != 0)
						{
							goto multi_select_end;
						}

						/* Code the current SELECT into temporary table "tab2"
						*/
						addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
						Debug.Assert(p.addrOpenEphm[1] == -1);
						p.addrOpenEphm[1] = addr;
						p.pPrior = null;
						pLimit = p.pLimit;
						p.pLimit = null;
						pOffset = p.pOffset;
						p.pOffset = null;
						intersectdest.iParm = tab2;
						explainSetInteger(ref iSub2, pParse.iNextSelectId);
						rc = sqlite3Select(pParse, p, ref intersectdest);
						testcase(rc != SQLITE_OK);
						p.pPrior = pPrior;
						if (p.nSelectRow > pPrior.nSelectRow)
							p.nSelectRow = pPrior.nSelectRow;
						sqlite3ExprDelete(db, ref p.pLimit);
						p.pLimit = pLimit;
						p.pOffset = pOffset;

						/* Generate code to take the intersection of the two temporary
						** tables.
						*/
						Debug.Assert(p.pEList != null);
						if (dest.eDest == SRT_Output)
						{
							Select pFirst = p;
							while (pFirst.pPrior != null)
								pFirst = pFirst.pPrior;
							generateColumnNames(pParse, null, pFirst.pEList);
						}
						iBreak = sqlite3VdbeMakeLabel(v);
						iCont = sqlite3VdbeMakeLabel(v);
						computeLimitRegisters(pParse, p, iBreak);
						sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak);
						r1 = sqlite3GetTempReg(pParse);
						iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1);
						sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
						sqlite3ReleaseTempReg(pParse, r1);
						selectInnerLoop(pParse, p, p.pEList, tab1, p.pEList.nExpr,
						null, -1, dest, iCont, iBreak);
						sqlite3VdbeResolveLabel(v, iCont);
						sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart);
						sqlite3VdbeResolveLabel(v, iBreak);
						sqlite3VdbeAddOp2(v, OP_Close, tab2, 0);
						sqlite3VdbeAddOp2(v, OP_Close, tab1, 0);
						break;
					}
			}

			explainComposite(pParse, p.op, iSub1, iSub2, p.op != TK_ALL);

			/* Compute collating sequences used by
			** temporary tables needed to implement the compound select.
			** Attach the KeyInfo structure to all temporary tables.
			**
			** This section is run by the right-most SELECT statement only.
			** SELECT statements to the left always skip this part.  The right-most
			** SELECT might also skip this part if it has no ORDER BY clause and
			** no temp tables are required.
			*/
			if ((p.selFlags & SF_UsesEphemeral) != 0)
			{
				int i;                        /* Loop counter */
				KeyInfo pKeyInfo;             /* Collating sequence for the result set */
				Select pLoop;                 /* For looping through SELECT statements */
				CollSeq apColl;               /* For looping through pKeyInfo.aColl[] */
				int nCol;                     /* Number of columns in result set */

				Debug.Assert(p.pRightmost == p);
				nCol = p.pEList.nExpr;
				pKeyInfo = new KeyInfo();           //sqlite3DbMallocZero(db,
				pKeyInfo.aColl = new CollSeq[nCol]; //sizeof(*pKeyInfo)+nCol*(CollSeq*.Length + 1));
				//if ( pKeyInfo == null )
				//{
				//  rc = SQLITE_NOMEM;
				//  goto multi_select_end;
				//}

				pKeyInfo.enc = db.aDbStatic[0].pSchema.enc;// ENC( pParse.db );
				pKeyInfo.nField = (u16)nCol;

				for (i = 0; i < nCol; i++)
				{//, apColl++){
					apColl = multiSelectCollSeq(pParse, p, i);
					if (null == apColl)
					{
						apColl = db.pDfltColl;
					}
					pKeyInfo.aColl[i] = apColl;
				}

				for (pLoop = p; pLoop != null; pLoop = pLoop.pPrior)
				{
					for (i = 0; i < 2; i++)
					{
						int addr = pLoop.addrOpenEphm[i];
						if (addr < 0)
						{
							/* If [0] is unused then [1] is also unused.  So we can
							** always safely abort as soon as the first unused slot is found */
							Debug.Assert(pLoop.addrOpenEphm[1] < 0);
							break;
						}
						sqlite3VdbeChangeP2(v, addr, nCol);
						sqlite3VdbeChangeP4(v, addr, pKeyInfo, P4_KEYINFO);
						pLoop.addrOpenEphm[i] = -1;
					}
				}
				sqlite3DbFree(db, ref pKeyInfo);
			}

		multi_select_end:
			pDest.iMem = dest.iMem;
			pDest.nMem = dest.nMem;
			sqlite3SelectDelete(db, ref pDelete);
			return rc;
		}

#endif // * SQLITE_OMIT_COMPOUND_SELECT */

		/*
** Code an output subroutine for a coroutine implementation of a
** SELECT statment.
**
** The data to be output is contained in pIn.iMem.  There are
** pIn.nMem columns to be output.  pDest is where the output should
** be sent.
**
** regReturn is the number of the register holding the subroutine
** return address.
**
** If regPrev>0 then it is the first register in a vector that
** records the previous output.  mem[regPrev] is a flag that is false
** if there has been no previous output.  If regPrev>0 then code is
** generated to suppress duplicates.  pKeyInfo is used for comparing
** keys.
**
** If the LIMIT found in p.iLimit is reached, jump immediately to
** iBreak.
*/

		private static int generateOutputSubroutine(
		Parse pParse,          /* Parsing context */
		Select p,              /* The SELECT statement */
		SelectDest pIn,        /* Coroutine supplying data */
		SelectDest pDest,      /* Where to send the data */
		int regReturn,         /* The return address register */
		int regPrev,           /* Previous result register.  No uniqueness if 0 */
		KeyInfo pKeyInfo,      /* For comparing with previous entry */
		int p4type,            /* The p4 type for pKeyInfo */
		int iBreak             /* Jump here if we hit the LIMIT */
		)
		{
			Vdbe v = pParse.pVdbe;
			int iContinue;
			int addr;

			addr = sqlite3VdbeCurrentAddr(v);
			iContinue = sqlite3VdbeMakeLabel(v);

			/* Suppress duplicates for UNION, EXCEPT, and INTERSECT
			*/
			if (regPrev != 0)
			{
				int j1, j2;
				j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev);
				j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn.iMem, regPrev + 1, pIn.nMem,
				pKeyInfo, p4type);
				sqlite3VdbeAddOp3(v, OP_Jump, j2 + 2, iContinue, j2 + 2);
				sqlite3VdbeJumpHere(v, j1);
				sqlite3ExprCodeCopy(pParse, pIn.iMem, regPrev + 1, pIn.nMem);
				sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev);
			}
			//if ( pParse.db.mallocFailed != 0 ) return 0;

			/* Suppress the the first OFFSET entries if there is an OFFSET clause
			*/
			codeOffset(v, p, iContinue);

			switch (pDest.eDest)
			{
				/* Store the result as data using a unique key.
				*/
				case SRT_Table:
				case SRT_EphemTab:
					{
						int r1 = sqlite3GetTempReg(pParse);
						int r2 = sqlite3GetTempReg(pParse);
						testcase(pDest.eDest == SRT_Table);
						testcase(pDest.eDest == SRT_EphemTab);
						sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn.iMem, pIn.nMem, r1);
						sqlite3VdbeAddOp2(v, OP_NewRowid, pDest.iParm, r2);
						sqlite3VdbeAddOp3(v, OP_Insert, pDest.iParm, r1, r2);
						sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
						sqlite3ReleaseTempReg(pParse, r2);
						sqlite3ReleaseTempReg(pParse, r1);
						break;
					}

#if !SQLITE_OMIT_SUBQUERY
				/* If we are creating a set for an "expr IN (SELECT ...)" construct,
** then there should be a single item on the stack.  Write this
** item into the set table with bogus data.
*/
				case SRT_Set:
					{
						int r1;
						Debug.Assert(pIn.nMem == 1);
						p.affinity =
						sqlite3CompareAffinity(p.pEList.a[0].pExpr, pDest.affinity);
						r1 = sqlite3GetTempReg(pParse);
						sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn.iMem, 1, r1, p.affinity, 1);
						sqlite3ExprCacheAffinityChange(pParse, pIn.iMem, 1);
						sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest.iParm, r1);
						sqlite3ReleaseTempReg(pParse, r1);
						break;
					}

#if FALSE  //* Never occurs on an ORDER BY query */
/* If any row exist in the result set, record that fact and abort.
*/
case SRT_Exists: {
sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest.iParm);
/* The LIMIT clause will terminate the loop for us */
break;
}
#endif

				/* If this is a scalar select that is part of an expression, then
** store the results in the appropriate memory cell and break out
** of the scan loop.
*/
				case SRT_Mem:
					{
						Debug.Assert(pIn.nMem == 1);
						sqlite3ExprCodeMove(pParse, pIn.iMem, pDest.iParm, 1);
						/* The LIMIT clause will jump out of the loop for us */
						break;
					}
#endif //* #if !SQLITE_OMIT_SUBQUERY */

				/* The results are stored in a sequence of registers
** starting at pDest.iMem.  Then the co-routine yields.
*/
				case SRT_Coroutine:
					{
						if (pDest.iMem == 0)
						{
							pDest.iMem = sqlite3GetTempRange(pParse, pIn.nMem);
							pDest.nMem = pIn.nMem;
						}
						sqlite3ExprCodeMove(pParse, pIn.iMem, pDest.iMem, pDest.nMem);
						sqlite3VdbeAddOp1(v, OP_Yield, pDest.iParm);
						break;
					}

				/* If none of the above, then the result destination must be
				** SRT_Output.  This routine is never called with any other
				** destination other than the ones handled above or SRT_Output.
				**
				** For SRT_Output, results are stored in a sequence of registers.
				** Then the OP_ResultRow opcode is used to cause sqlite3_step() to
				** return the next row of result.
				*/
				default:
					{
						Debug.Assert(pDest.eDest == SRT_Output);
						sqlite3VdbeAddOp2(v, OP_ResultRow, pIn.iMem, pIn.nMem);
						sqlite3ExprCacheAffinityChange(pParse, pIn.iMem, pIn.nMem);
						break;
					}
			}

			/* Jump to the end of the loop if the LIMIT is reached.
			*/
			if (p.iLimit != 0)
			{
				sqlite3VdbeAddOp3(v, OP_IfZero, p.iLimit, iBreak, -1);
			}

			/* Generate the subroutine return
			*/
			sqlite3VdbeResolveLabel(v, iContinue);
			sqlite3VdbeAddOp1(v, OP_Return, regReturn);

			return addr;
		}

		/*
		** Alternative compound select code generator for cases when there
		** is an ORDER BY clause.
		**
		** We assume a query of the following form:
		**
		**      <selectA>  <operator>  <selectB>  ORDER BY <orderbylist>
		**
		** <operator> is one of UNION ALL, UNION, EXCEPT, or INTERSECT.  The idea
		** is to code both <selectA> and <selectB> with the ORDER BY clause as
		** co-routines.  Then run the co-routines in parallel and merge the results
		** into the output.  In addition to the two coroutines (called selectA and
		** selectB) there are 7 subroutines:
		**
		**    outA:    Move the output of the selectA coroutine into the output
		**             of the compound query.
		**
		**    outB:    Move the output of the selectB coroutine into the output
		**             of the compound query.  (Only generated for UNION and
		**             UNION ALL.  EXCEPT and INSERTSECT never output a row that
		**             appears only in B.)
		**
		**    AltB:    Called when there is data from both coroutines and A<B.
		**
		**    AeqB:    Called when there is data from both coroutines and A==B.
		**
		**    AgtB:    Called when there is data from both coroutines and A>B.
		**
		**    EofA:    Called when data is exhausted from selectA.
		**
		**    EofB:    Called when data is exhausted from selectB.
		**
		** The implementation of the latter five subroutines depend on which
		** <operator> is used:
		**
		**
		**             UNION ALL         UNION            EXCEPT          INTERSECT
		**          -------------  -----------------  --------------  -----------------
		**   AltB:   outA, nextA      outA, nextA       outA, nextA         nextA
		**
		**   AeqB:   outA, nextA         nextA             nextA         outA, nextA
		**
		**   AgtB:   outB, nextB      outB, nextB          nextB            nextB
		**
		**   EofA:   outB, nextB      outB, nextB          halt             halt
		**
		**   EofB:   outA, nextA      outA, nextA       outA, nextA         halt
		**
		** In the AltB, AeqB, and AgtB subroutines, an EOF on A following nextA
		** causes an immediate jump to EofA and an EOF on B following nextB causes
		** an immediate jump to EofB.  Within EofA and EofB, and EOF on entry or
		** following nextX causes a jump to the end of the select processing.
		**
		** Duplicate removal in the UNION, EXCEPT, and INTERSECT cases is handled
		** within the output subroutine.  The regPrev register set holds the previously
		** output value.  A comparison is made against this value and the output
		** is skipped if the next results would be the same as the previous.
		**
		** The implementation plan is to implement the two coroutines and seven
		** subroutines first, then put the control logic at the bottom.  Like this:
		**
		**          goto Init
		**     coA: coroutine for left query (A)
		**     coB: coroutine for right query (B)
		**    outA: output one row of A
		**    outB: output one row of B (UNION and UNION ALL only)
		**    EofA: ...
		**    EofB: ...
		**    AltB: ...
		**    AeqB: ...
		**    AgtB: ...
		**    Init: initialize coroutine registers
		**          yield coA
		**          if eof(A) goto EofA
		**          yield coB
		**          if eof(B) goto EofB
		**    Cmpr: Compare A, B
		**          Jump AltB, AeqB, AgtB
		**     End: ...
		**
		** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not
		** actually called using Gosub and they do not Return.  EofA and EofB loop
		** until all data is exhausted then jump to the "end" labe.  AltB, AeqB,
		** and AgtB jump to either L2 or to one of EofA or EofB.
		*/
#if !SQLITE_OMIT_COMPOUND_SELECT

		private static int multiSelectOrderBy(
		Parse pParse,         /* Parsing context */
		Select p,             /* The right-most of SELECTs to be coded */
		SelectDest pDest      /* What to do with query results */
		)
		{
			int i, j;             /* Loop counters */
			Select pPrior;        /* Another SELECT immediately to our left */
			Vdbe v;               /* Generate code to this VDBE */
			SelectDest destA = new SelectDest();     /* Destination for coroutine A */
			SelectDest destB = new SelectDest();     /* Destination for coroutine B */
			int regAddrA;         /* Address register for select-A coroutine */
			int regEofA;          /* Flag to indicate when select-A is complete */
			int regAddrB;         /* Address register for select-B coroutine */
			int regEofB;          /* Flag to indicate when select-B is complete */
			int addrSelectA;      /* Address of the select-A coroutine */
			int addrSelectB;      /* Address of the select-B coroutine */
			int regOutA;          /* Address register for the output-A subroutine */
			int regOutB;          /* Address register for the output-B subroutine */
			int addrOutA;         /* Address of the output-A subroutine */
			int addrOutB = 0;     /* Address of the output-B subroutine */
			int addrEofA;         /* Address of the select-A-exhausted subroutine */
			int addrEofB;         /* Address of the select-B-exhausted subroutine */
			int addrAltB;         /* Address of the A<B subroutine */
			int addrAeqB;         /* Address of the A==B subroutine */
			int addrAgtB;         /* Address of the A>B subroutine */
			int regLimitA;        /* Limit register for select-A */
			int regLimitB;        /* Limit register for select-A */
			int regPrev;          /* A range of registers to hold previous output */
			int savedLimit;       /* Saved value of p.iLimit */
			int savedOffset;      /* Saved value of p.iOffset */
			int labelCmpr;        /* Label for the start of the merge algorithm */
			int labelEnd;         /* Label for the end of the overall SELECT stmt */
			int j1;               /* Jump instructions that get retargetted */
			int op;               /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */
			KeyInfo pKeyDup = null;      /* Comparison information for duplicate removal */
			KeyInfo pKeyMerge;    /* Comparison information for merging rows */
			sqlite3 db;           /* Database connection */
			ExprList pOrderBy;    /* The ORDER BY clause */
			int nOrderBy;         /* Number of terms in the ORDER BY clause */
			int[] aPermute;       /* Mapping from ORDER BY terms to result set columns */
#if !SQLITE_OMIT_EXPLAIN
			int iSub1 = 0;            /* EQP id of left-hand query */
			int iSub2 = 0;            /* EQP id of right-hand query */
#endif

			Debug.Assert(p.pOrderBy != null);
			Debug.Assert(pKeyDup == null); /* "Managed" code needs this.  Ticket #3382. */
			db = pParse.db;
			v = pParse.pVdbe;
			Debug.Assert(v != null);       /* Already thrown the error if VDBE alloc failed */
			labelEnd = sqlite3VdbeMakeLabel(v);
			labelCmpr = sqlite3VdbeMakeLabel(v);

			/* Patch up the ORDER BY clause
			*/
			op = p.op;
			pPrior = p.pPrior;
			Debug.Assert(pPrior.pOrderBy == null);
			pOrderBy = p.pOrderBy;
			Debug.Assert(pOrderBy != null);
			nOrderBy = pOrderBy.nExpr;

			/* For operators other than UNION ALL we have to make sure that
			** the ORDER BY clause covers every term of the result set.  Add
			** terms to the ORDER BY clause as necessary.
			*/
			if (op != TK_ALL)
			{
				for (i = 1; /* db.mallocFailed == 0 && */ i <= p.pEList.nExpr; i++)
				{
					ExprList_item pItem;
					for (j = 0; j < nOrderBy; j++)//, pItem++)
					{
						pItem = pOrderBy.a[j];
						Debug.Assert(pItem.iCol > 0);
						if (pItem.iCol == i)
							break;
					}
					if (j == nOrderBy)
					{
						Expr pNew = sqlite3Expr(db, TK_INTEGER, null);
						//if ( pNew == null )
						//  return SQLITE_NOMEM;
						pNew.flags |= EP_IntValue;
						pNew.u.iValue = i;
						pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
						pOrderBy.a[nOrderBy++].iCol = (u16)i;
					}
				}
			}

			/* Compute the comparison permutation and keyinfo that is used with
			** the permutation used to determine if the next
			** row of results comes from selectA or selectB.  Also add explicit
			** collations to the ORDER BY clause terms so that when the subqueries
			** to the right and the left are evaluated, they use the correct
			** collation.
			*/
			aPermute = new int[nOrderBy];// sqlite3DbMallocRaw( db, sizeof( int ) * nOrderBy );
			if (aPermute != null)
			{
				ExprList_item pItem;
				for (i = 0; i < nOrderBy; i++)//, pItem++)
				{
					pItem = pOrderBy.a[i];
					Debug.Assert(pItem.iCol > 0 && pItem.iCol <= p.pEList.nExpr);
					aPermute[i] = pItem.iCol - 1;
				}
				pKeyMerge = new KeyInfo();//      sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq)+1));
				if (pKeyMerge != null)
				{
					pKeyMerge.aColl = new CollSeq[nOrderBy];
					pKeyMerge.aSortOrder = new byte[nOrderBy];//(u8)&pKeyMerge.aColl[nOrderBy];
					pKeyMerge.nField = (u16)nOrderBy;
					pKeyMerge.enc = ENC(db);
					for (i = 0; i < nOrderBy; i++)
					{
						CollSeq pColl;
						Expr pTerm = pOrderBy.a[i].pExpr;
						if ((pTerm.flags & EP_ExpCollate) != 0)
						{
							pColl = pTerm.pColl;
						}
						else
						{
							pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
							pTerm.flags |= EP_ExpCollate;
							pTerm.pColl = pColl;
						}
						pKeyMerge.aColl[i] = pColl;
						pKeyMerge.aSortOrder[i] = (byte)pOrderBy.a[i].sortOrder;
					}
				}
			}
			else
			{
				pKeyMerge = null;
			}

			/* Reattach the ORDER BY clause to the query.
			*/
			p.pOrderBy = pOrderBy;
			pPrior.pOrderBy = sqlite3ExprListDup(pParse.db, pOrderBy, 0);

			/* Allocate a range of temporary registers and the KeyInfo needed
			** for the logic that removes duplicate result rows when the
			** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL).
			*/
			if (op == TK_ALL)
			{
				regPrev = 0;
			}
			else
			{
				int nExpr = p.pEList.nExpr;
				Debug.Assert(nOrderBy >= nExpr /*|| db.mallocFailed != 0 */ );
				regPrev = sqlite3GetTempRange(pParse, nExpr + 1);
				sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev);
				pKeyDup = new KeyInfo();//sqlite3DbMallocZero(db,
				//sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq)+1) );
				if (pKeyDup != null)
				{
					pKeyDup.aColl = new CollSeq[nExpr];
					pKeyDup.aSortOrder = new byte[nExpr];//(u8)&pKeyDup.aColl[nExpr];
					pKeyDup.nField = (u16)nExpr;
					pKeyDup.enc = ENC(db);
					for (i = 0; i < nExpr; i++)
					{
						pKeyDup.aColl[i] = multiSelectCollSeq(pParse, p, i);
						pKeyDup.aSortOrder[i] = 0;
					}
				}
			}

			/* Separate the left and the right query from one another
			*/
			p.pPrior = null;
			sqlite3ResolveOrderGroupBy(pParse, p, p.pOrderBy, "ORDER");
			if (pPrior.pPrior == null)
			{
				sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior.pOrderBy, "ORDER");
			}

			/* Compute the limit registers */
			computeLimitRegisters(pParse, p, labelEnd);
			if (p.iLimit != 0 && op == TK_ALL)
			{
				regLimitA = ++pParse.nMem;
				regLimitB = ++pParse.nMem;
				sqlite3VdbeAddOp2(v, OP_Copy, (p.iOffset != 0) ? p.iOffset + 1 : p.iLimit,
				regLimitA);
				sqlite3VdbeAddOp2(v, OP_Copy, regLimitA, regLimitB);
			}
			else
			{
				regLimitA = regLimitB = 0;
			}
			sqlite3ExprDelete(db, ref p.pLimit);
			p.pLimit = null;
			sqlite3ExprDelete(db, ref p.pOffset);
			p.pOffset = null;

			regAddrA = ++pParse.nMem;
			regEofA = ++pParse.nMem;
			regAddrB = ++pParse.nMem;
			regEofB = ++pParse.nMem;
			regOutA = ++pParse.nMem;
			regOutB = ++pParse.nMem;
			sqlite3SelectDestInit(destA, SRT_Coroutine, regAddrA);
			sqlite3SelectDestInit(destB, SRT_Coroutine, regAddrB);

			/* Jump past the various subroutines and coroutines to the main
			** merge loop
			*/
			j1 = sqlite3VdbeAddOp0(v, OP_Goto);
			addrSelectA = sqlite3VdbeCurrentAddr(v);

			/* Generate a coroutine to evaluate the SELECT statement to the
			** left of the compound operator - the "A" select.
			*/
			VdbeNoopComment(v, "Begin coroutine for left SELECT");
			pPrior.iLimit = regLimitA;
			explainSetInteger(ref iSub1, pParse.iNextSelectId);
			sqlite3Select(pParse, pPrior, ref destA);
			sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA);
			sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
			VdbeNoopComment(v, "End coroutine for left SELECT");

			/* Generate a coroutine to evaluate the SELECT statement on
			** the right - the "B" select
			*/
			addrSelectB = sqlite3VdbeCurrentAddr(v);
			VdbeNoopComment(v, "Begin coroutine for right SELECT");
			savedLimit = p.iLimit;
			savedOffset = p.iOffset;
			p.iLimit = regLimitB;
			p.iOffset = 0;
			explainSetInteger(ref iSub2, pParse.iNextSelectId);
			sqlite3Select(pParse, p, ref destB);
			p.iLimit = savedLimit;
			p.iOffset = savedOffset;
			sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB);
			sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
			VdbeNoopComment(v, "End coroutine for right SELECT");

			/* Generate a subroutine that outputs the current row of the A
			** select as the next output row of the compound select.
			*/
			VdbeNoopComment(v, "Output routine for A");
			addrOutA = generateOutputSubroutine(pParse,
			p, destA, pDest, regOutA,
			regPrev, pKeyDup, P4_KEYINFO_HANDOFF, labelEnd);

			/* Generate a subroutine that outputs the current row of the B
			** select as the next output row of the compound select.
			*/
			if (op == TK_ALL || op == TK_UNION)
			{
				VdbeNoopComment(v, "Output routine for B");
				addrOutB = generateOutputSubroutine(pParse,
				p, destB, pDest, regOutB,
				regPrev, pKeyDup, P4_KEYINFO_STATIC, labelEnd);
			}

			/* Generate a subroutine to run when the results from select A
			** are exhausted and only data in select B remains.
			*/
			VdbeNoopComment(v, "eof-A subroutine");
			if (op == TK_EXCEPT || op == TK_INTERSECT)
			{
				addrEofA = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelEnd);
			}
			else
			{
				addrEofA = sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd);
				sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
				sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
				sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA);
				p.nSelectRow += pPrior.nSelectRow;
			}

			/* Generate a subroutine to run when the results from select B
			** are exhausted and only data in select A remains.
			*/
			if (op == TK_INTERSECT)
			{
				addrEofB = addrEofA;
				if (p.nSelectRow > pPrior.nSelectRow)
					p.nSelectRow = pPrior.nSelectRow;
			}
			else
			{
				VdbeNoopComment(v, "eof-B subroutine");
				addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
				sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
				sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
				sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB);
			}

			/* Generate code to handle the case of A<B
			*/
			VdbeNoopComment(v, "A-lt-B subroutine");
			addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
			sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
			sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
			sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);

			/* Generate code to handle the case of A==B
			*/
			if (op == TK_ALL)
			{
				addrAeqB = addrAltB;
			}
			else if (op == TK_INTERSECT)
			{
				addrAeqB = addrAltB;
				addrAltB++;
			}
			else
			{
				VdbeNoopComment(v, "A-eq-B subroutine");
				addrAeqB =
				sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
				sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
				sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
			}

			/* Generate code to handle the case of A>B
			*/
			VdbeNoopComment(v, "A-gt-B subroutine");
			addrAgtB = sqlite3VdbeCurrentAddr(v);
			if (op == TK_ALL || op == TK_UNION)
			{
				sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
			}
			sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
			sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB);
			sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);

			/* This code runs once to initialize everything.
			*/
			sqlite3VdbeJumpHere(v, j1);
			sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofA);
			sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofB);
			sqlite3VdbeAddOp2(v, OP_Gosub, regAddrA, addrSelectA);
			sqlite3VdbeAddOp2(v, OP_Gosub, regAddrB, addrSelectB);
			sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
			sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB);

			/* Implement the main merge loop
			*/
			sqlite3VdbeResolveLabel(v, labelCmpr);
			sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, aPermute, P4_INTARRAY);
			sqlite3VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, nOrderBy,
			pKeyMerge, P4_KEYINFO_HANDOFF);
			sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);

			/* Release temporary registers
			*/
			if (regPrev != 0)
			{
				sqlite3ReleaseTempRange(pParse, regPrev, nOrderBy + 1);
			}

			/* Jump to the this point in order to terminate the query.
			*/
			sqlite3VdbeResolveLabel(v, labelEnd);

			/* Set the number of output columns
			*/
			if (pDest.eDest == SRT_Output)
			{
				Select pFirst = pPrior;
				while (pFirst.pPrior != null)
					pFirst = pFirst.pPrior;
				generateColumnNames(pParse, null, pFirst.pEList);
			}

			/* Reassembly the compound query so that it will be freed correctly
			** by the calling function */
			if (p.pPrior != null)
			{
				sqlite3SelectDelete(db, ref p.pPrior);
			}
			p.pPrior = pPrior;

			/*** TBD:  Insert subroutine calls to close cursors on incomplete
			**** subqueries ****/
			explainComposite(pParse, p.op, iSub1, iSub2, false);
			return SQLITE_OK;
		}

#endif
#if !(SQLITE_OMIT_SUBQUERY) || !(SQLITE_OMIT_VIEW)
		/* Forward Declarations */
		//static void substExprList(sqlite3*, ExprList*, int, ExprList);
		//static void substSelect(sqlite3*, Select *, int, ExprList );

		/*
		** Scan through the expression pExpr.  Replace every reference to
		** a column in table number iTable with a copy of the iColumn-th
		** entry in pEList.  (But leave references to the ROWID column
		** unchanged.)
		**
		** This routine is part of the flattening procedure.  A subquery
		** whose result set is defined by pEList appears as entry in the
		** FROM clause of a SELECT such that the VDBE cursor assigned to that
		** FORM clause entry is iTable.  This routine make the necessary
		** changes to pExpr so that it refers directly to the source table
		** of the subquery rather the result set of the subquery.
		*/

		private static Expr substExpr(
		sqlite3 db,        /* Report malloc errors to this connection */
		Expr pExpr,        /* Expr in which substitution occurs */
		int iTable,        /* Table to be substituted */
		ExprList pEList    /* Substitute expressions */
		)
		{
			if (pExpr == null)
				return null;
			if (pExpr.op == TK_COLUMN && pExpr.iTable == iTable)
			{
				if (pExpr.iColumn < 0)
				{
					pExpr.op = TK_NULL;
				}
				else
				{
					Expr pNew;
					Debug.Assert(pEList != null && pExpr.iColumn < pEList.nExpr);
					Debug.Assert(pExpr.pLeft == null && pExpr.pRight == null);
					pNew = sqlite3ExprDup(db, pEList.a[pExpr.iColumn].pExpr, 0);
					if (pExpr.pColl != null)
					{
						pNew.pColl = pExpr.pColl;
					}
					sqlite3ExprDelete(db, ref pExpr);
					pExpr = pNew;
				}
			}
			else
			{
				pExpr.pLeft = substExpr(db, pExpr.pLeft, iTable, pEList);
				pExpr.pRight = substExpr(db, pExpr.pRight, iTable, pEList);
				if (ExprHasProperty(pExpr, EP_xIsSelect))
				{
					substSelect(db, pExpr.x.pSelect, iTable, pEList);
				}
				else
				{
					substExprList(db, pExpr.x.pList, iTable, pEList);
				}
			}
			return pExpr;
		}

		private static void substExprList(
		sqlite3 db,         /* Report malloc errors here */
		ExprList pList,     /* List to scan and in which to make substitutes */
		int iTable,          /* Table to be substituted */
		ExprList pEList     /* Substitute values */
		)
		{
			int i;
			if (pList == null)
				return;
			for (i = 0; i < pList.nExpr; i++)
			{
				pList.a[i].pExpr = substExpr(db, pList.a[i].pExpr, iTable, pEList);
			}
		}

		private static void substSelect(
		sqlite3 db,         /* Report malloc errors here */
		Select p,           /* SELECT statement in which to make substitutions */
		int iTable,          /* Table to be replaced */
		ExprList pEList     /* Substitute values */
		)
		{
			SrcList pSrc;
			SrcList_item pItem;
			int i;
			if (p == null)
				return;
			substExprList(db, p.pEList, iTable, pEList);
			substExprList(db, p.pGroupBy, iTable, pEList);
			substExprList(db, p.pOrderBy, iTable, pEList);
			p.pHaving = substExpr(db, p.pHaving, iTable, pEList);
			p.pWhere = substExpr(db, p.pWhere, iTable, pEList);
			substSelect(db, p.pPrior, iTable, pEList);
			pSrc = p.pSrc;
			Debug.Assert(pSrc != null);  /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */
			if (ALWAYS(pSrc))
			{
				for (i = pSrc.nSrc; i > 0; i--)//, pItem++ )
				{
					pItem = pSrc.a[pSrc.nSrc - i];
					substSelect(db, pItem.pSelect, iTable, pEList);
				}
			}
		}

#endif //* !SQLITE_OMIT_SUBQUERY) || !SQLITE_OMIT_VIEW) */

#if !(SQLITE_OMIT_SUBQUERY) || !(SQLITE_OMIT_VIEW)
		/*
** This routine attempts to flatten subqueries in order to speed
** execution.  It returns 1 if it makes changes and 0 if no flattening
** occurs.
**
** To understand the concept of flattening, consider the following
** query:
**
**     SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5
**
** The default way of implementing this query is to execute the
** subquery first and store the results in a temporary table, then
** run the outer query on that temporary table.  This requires two
** passes over the data.  Furthermore, because the temporary table
** has no indices, the WHERE clause on the outer query cannot be
** optimized.
**
** This routine attempts to rewrite queries such as the above into
** a single flat select, like this:
**
**     SELECT x+y AS a FROM t1 WHERE z<100 AND a>5
**
** The code generated for this simpification gives the same result
** but only has to scan the data once.  And because indices might
** exist on the table t1, a complete scan of the data might be
** avoided.
**
** Flattening is only attempted if all of the following are true:
**
**   (1)  The subquery and the outer query do not both use aggregates.
**
**   (2)  The subquery is not an aggregate or the outer query is not a join.
**
**   (3)  The subquery is not the right operand of a left outer join
**        (Originally ticket #306.  Strengthened by ticket #3300)
**
**   (4)  The subquery is not DISTINCT.
**
**  (*)  At one point restrictions (4) and (5) defined a subset of DISTINCT
**        sub-queries that were excluded from this optimization. Restriction
**        (4) has since been expanded to exclude all DISTINCT subqueries.
**
**   (6)  The subquery does not use aggregates or the outer query is not
**        DISTINCT.
**
**   (7)  The subquery has a FROM clause.
**
**   (8)  The subquery does not use LIMIT or the outer query is not a join.
**
**   (9)  The subquery does not use LIMIT or the outer query does not use
**        aggregates.
**
**  (10)  The subquery does not use aggregates or the outer query does not
**        use LIMIT.
**
**  (11)  The subquery and the outer query do not both have ORDER BY clauses.
**
**  (*)  Not implemented.  Subsumed into restriction (3).  Was previously
**        a separate restriction deriving from ticket #350.
**
**  (13)  The subquery and outer query do not both use LIMIT.
**
**  (14)  The subquery does not use OFFSET.
**
**  (15)  The outer query is not part of a compound select or the
**        subquery does not have a LIMIT clause.
**        (See ticket #2339 and ticket [02a8e81d44]).
**
**  (16)  The outer query is not an aggregate or the subquery does
**        not contain ORDER BY.  (Ticket #2942)  This used to not matter
**        until we introduced the group_concat() function.
**
**  (17)  The sub-query is not a compound select, or it is a UNION ALL
**        compound clause made up entirely of non-aggregate queries, and
**        the parent query:
**
**          * is not itself part of a compound select,
**          * is not an aggregate or DISTINCT query, and
**          * has no other tables or sub-selects in the FROM clause.
**
**        The parent and sub-query may contain WHERE clauses. Subject to
**        rules (11), (13) and (14), they may also contain ORDER BY,
**        LIMIT and OFFSET clauses.
**
**  (18)  If the sub-query is a compound select, then all terms of the
**        ORDER by clause of the parent must be simple references to
**        columns of the sub-query.
**
**  (19)  The subquery does not use LIMIT or the outer query does not
**        have a WHERE clause.
**
**  (20)  If the sub-query is a compound select, then it must not use
**        an ORDER BY clause.  Ticket #3773.  We could relax this constraint
**        somewhat by saying that the terms of the ORDER BY clause must
**        appear as unmodified result columns in the outer query.  But
**        have other optimizations in mind to deal with that case.
**
**  (21)  The subquery does not use LIMIT or the outer query is not
**        DISTINCT.  (See ticket [752e1646fc]).
**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p.pSrc.a[iFrom].  isAgg is true if the outer query
** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
**
** If flattening is not attempted, this routine is a no-op and returns 0.
** If flattening is attempted this routine returns 1.
**
** All of the expression analysis must occur on both the outer query and
** the subquery before this routine runs.
*/

		private static int flattenSubquery(
		Parse pParse,        /* Parsing context */
		Select p,            /* The parent or outer SELECT statement */
		int iFrom,           /* Index in p.pSrc.a[] of the inner subquery */
		bool isAgg,          /* True if outer SELECT uses aggregate functions */
		bool subqueryIsAgg   /* True if the subquery uses aggregate functions */
		)
		{
			string zSavedAuthContext = pParse.zAuthContext;
			Select pParent;
			Select pSub;         /* The inner query or "subquery" */
			Select pSub1;      /* Pointer to the rightmost select in sub-query */
			SrcList pSrc;        /* The FROM clause of the outer query */
			SrcList pSubSrc;     /* The FROM clause of the subquery */
			ExprList pList;      /* The result set of the outer query */
			int iParent;         /* VDBE cursor number of the pSub result set temp table */
			int i;               /* Loop counter */
			Expr pWhere;         /* The WHERE clause */
			SrcList_item pSubitem;/* The subquery */
			sqlite3 db = pParse.db;

			/* Check to see if flattening is permitted.  Return 0 if not.
			*/
			Debug.Assert(p != null);
			Debug.Assert(p.pPrior == null);  /* Unable to flatten compound queries */
			if ((db.flags & SQLITE_QueryFlattener) != 0)
				return 0;
			pSrc = p.pSrc;
			Debug.Assert(pSrc != null && iFrom >= 0 && iFrom < pSrc.nSrc);
			pSubitem = pSrc.a[iFrom];
			iParent = pSubitem.iCursor;
			pSub = pSubitem.pSelect;
			Debug.Assert(pSub != null);
			if (isAgg && subqueryIsAgg)
				return 0;                 /* Restriction (1)  */
			if (subqueryIsAgg && pSrc.nSrc > 1)
				return 0;          /* Restriction (2)  */
			pSubSrc = pSub.pSrc;
			Debug.Assert(pSubSrc != null);
			/* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
			** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET
			** because they could be computed at compile-time.  But when LIMIT and OFFSET
			** became arbitrary expressions, we were forced to add restrictions (13)
			** and (14). */
			if (pSub.pLimit != null && p.pLimit != null)
				return 0;  /* Restriction (13) */
			if (pSub.pOffset != null)
				return 0;                     /* Restriction (14) */
			if (p.pRightmost != null && pSub.pLimit != null)
			{
				return 0;                                               /* Restriction (15) */
			}
			if (pSubSrc.nSrc == 0)
				return 0;                        /* Restriction (7)  */
			if ((pSub.selFlags & SF_Distinct) != 0)
				return 0;     /* Restriction (5)  */
			if (pSub.pLimit != null && (pSrc.nSrc > 1 || isAgg))
			{
				return 0;         /* Restrictions (8)(9) */
			}
			if ((p.selFlags & SF_Distinct) != 0 && subqueryIsAgg)
			{
				return 0;         /* Restriction (6)  */
			}
			if (p.pOrderBy != null && pSub.pOrderBy != null)
			{
				return 0;                                           /* Restriction (11) */
			}
			if (isAgg && pSub.pOrderBy != null)
				return 0;                /* Restriction (16) */
			if (pSub.pLimit != null && p.pWhere != null)
				return 0;              /* Restriction (19) */
			if (pSub.pLimit != null && (p.selFlags & SF_Distinct) != 0)
			{
				return 0;         /* Restriction (21) */
			}

			/* OBSOLETE COMMENT 1:
			** Restriction 3:  If the subquery is a join, make sure the subquery is
			** not used as the right operand of an outer join.  Examples of why this
			** is not allowed:
			**
			**         t1 LEFT OUTER JOIN (t2 JOIN t3)
			**
			** If we flatten the above, we would get
			**
			**         (t1 LEFT OUTER JOIN t2) JOIN t3
			**
			** which is not at all the same thing.
			**
			** OBSOLETE COMMENT 2:
			** Restriction 12:  If the subquery is the right operand of a left outer

			/* Restriction 12:  If the subquery is the right operand of a left outer
			** join, make sure the subquery has no WHERE clause.
			** An examples of why this is not allowed:
			**
			**         t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0)
			**
			** If we flatten the above, we would get
			**
			**         (t1 LEFT OUTER JOIN t2) WHERE t2.x>0
			**
			** But the t2.x>0 test will always fail on a NULL row of t2, which
			** effectively converts the OUTER JOIN into an INNER JOIN.
			**
			** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE:
			** Ticket #3300 shows that flattening the right term of a LEFT JOIN
			** is fraught with danger.  Best to avoid the whole thing.  If the
			** subquery is the right term of a LEFT JOIN, then do not flatten.
			*/
			if ((pSubitem.jointype & JT_OUTER) != 0)
			{
				return 0;
			}

			/* Restriction 17: If the sub-query is a compound SELECT, then it must
			** use only the UNION ALL operator. And none of the simple select queries
			** that make up the compound SELECT are allowed to be aggregate or distinct
			** queries.
			*/
			if (pSub.pPrior != null)
			{
				if (pSub.pOrderBy != null)
				{
					return 0;  /* Restriction 20 */
				}
				if (isAgg || (p.selFlags & SF_Distinct) != 0 || pSrc.nSrc != 1)
				{
					return 0;
				}
				for (pSub1 = pSub; pSub1 != null; pSub1 = pSub1.pPrior)
				{
					testcase((pSub1.selFlags & (SF_Distinct | SF_Aggregate)) == SF_Distinct);
					testcase((pSub1.selFlags & (SF_Distinct | SF_Aggregate)) == SF_Aggregate);
					if ((pSub1.selFlags & (SF_Distinct | SF_Aggregate)) != 0
					|| (pSub1.pPrior != null && pSub1.op != TK_ALL)
					|| NEVER(pSub1.pSrc == null) || pSub1.pSrc.nSrc != 1
					)
					{
						return 0;
					}
				}

				/* Restriction 18. */
				if (p.pOrderBy != null)
				{
					int ii;
					for (ii = 0; ii < p.pOrderBy.nExpr; ii++)
					{
						if (p.pOrderBy.a[ii].iCol == 0)
							return 0;
					}
				}
			}

			/***** If we reach this point, flattening is permitted. *****/

			/* Authorize the subquery */
			pParse.zAuthContext = pSubitem.zName;
			sqlite3AuthCheck(pParse, SQLITE_SELECT, null, null, null);
			pParse.zAuthContext = zSavedAuthContext;

			/* If the sub-query is a compound SELECT statement, then (by restrictions
			** 17 and 18 above) it must be a UNION ALL and the parent query must
			** be of the form:
			**
			**     SELECT <expr-list> FROM (<sub-query>) <where-clause>
			**
			** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block
			** creates N-1 copies of the parent query without any ORDER BY, LIMIT or
			** OFFSET clauses and joins them to the left-hand-side of the original
			** using UNION ALL operators. In this case N is the number of simple
			** select statements in the compound sub-query.
			**
			** Example:
			**
			**     SELECT a+1 FROM (
			**        SELECT x FROM tab
			**        UNION ALL
			**        SELECT y FROM tab
			**        UNION ALL
			**        SELECT abs(z*2) FROM tab2
			**     ) WHERE a!=5 ORDER BY 1
			**
			** Transformed into:
			**
			**     SELECT x+1 FROM tab WHERE x+1!=5
			**     UNION ALL
			**     SELECT y+1 FROM tab WHERE y+1!=5
			**     UNION ALL
			**     SELECT abs(z*2)+1 FROM tab2 WHERE abs(z*2)+1!=5
			**     ORDER BY 1
			**
			** We call this the "compound-subquery flattening".
			*/
			for (pSub = pSub.pPrior; pSub != null; pSub = pSub.pPrior)
			{
				Select pNew;
				ExprList pOrderBy = p.pOrderBy;
				Expr pLimit = p.pLimit;
				Select pPrior = p.pPrior;
				p.pOrderBy = null;
				p.pSrc = null;
				p.pPrior = null;
				p.pLimit = null;
				pNew = sqlite3SelectDup(db, p, 0);
				p.pLimit = pLimit;
				p.pOrderBy = pOrderBy;
				p.pSrc = pSrc;
				p.op = TK_ALL;
				p.pRightmost = null;
				if (pNew == null)
				{
					pNew = pPrior;
				}
				else
				{
					pNew.pPrior = pPrior;
					pNew.pRightmost = null;
				}
				p.pPrior = pNew;
				//        if ( db.mallocFailed != 0 ) return 1;
			}

			/* Begin flattening the iFrom-th entry of the FROM clause
			** in the outer query.
			*/
			pSub = pSub1 = pSubitem.pSelect;
			/* Delete the transient table structure associated with the
			** subquery
			*/

			sqlite3DbFree(db, ref pSubitem.zDatabase);
			sqlite3DbFree(db, ref pSubitem.zName);
			sqlite3DbFree(db, ref pSubitem.zAlias);
			pSubitem.zDatabase = null;
			pSubitem.zName = null;
			pSubitem.zAlias = null;
			pSubitem.pSelect = null;
			/* Defer deleting the Table object associated with the
			** subquery until code generation is
			** complete, since there may still exist Expr.pTab entries that
			** refer to the subquery even after flattening.  Ticket #3346.
			**
			** pSubitem->pTab is always non-NULL by test restrictions and tests above.
			*/
			if (ALWAYS(pSubitem.pTab != null))
			{
				Table pTabToDel = pSubitem.pTab;
				if (pTabToDel.nRef == 1)
				{
					Parse pToplevel = sqlite3ParseToplevel(pParse);
					pTabToDel.pNextZombie = pToplevel.pZombieTab;
					pToplevel.pZombieTab = pTabToDel;
				}
				else
				{
					pTabToDel.nRef--;
				}
				pSubitem.pTab = null;
			}

			/* The following loop runs once for each term in a compound-subquery
			** flattening (as described above).  If we are doing a different kind
			** of flattening - a flattening other than a compound-subquery flattening -
			** then this loop only runs once.
			**
			** This loop moves all of the FROM elements of the subquery into the
			** the FROM clause of the outer query.  Before doing this, remember
			** the cursor number for the original outer query FROM element in
			** iParent.  The iParent cursor will never be used.  Subsequent code
			** will scan expressions looking for iParent references and replace
			** those references with expressions that resolve to the subquery FROM
			** elements we are now copying in.
			*/
			for (pParent = p; pParent != null; pParent = pParent.pPrior, pSub = pSub.pPrior)
			{
				int nSubSrc;
				u8 jointype = 0;
				pSubSrc = pSub.pSrc;     /* FROM clause of subquery */
				nSubSrc = pSubSrc.nSrc;  /* Number of terms in subquery FROM clause */
				pSrc = pParent.pSrc;     /* FROM clause of the outer query */

				if (pSrc != null)
				{
					Debug.Assert(pParent == p);  /* First time through the loop */
					jointype = pSubitem.jointype;
				}
				else
				{
					Debug.Assert(pParent != p);  /* 2nd and subsequent times through the loop */
					pSrc = pParent.pSrc = sqlite3SrcListAppend(db, null, null, null);
					//if ( pSrc == null )
					//{
					//  //Debug.Assert( db.mallocFailed != 0 );
					//  break;
					//}
				}

				/* The subquery uses a single slot of the FROM clause of the outer
				** query.  If the subquery has more than one element in its FROM clause,
				** then expand the outer query to make space for it to hold all elements
				** of the subquery.
				**
				** Example:
				**
				**    SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB;
				**
				** The outer query has 3 slots in its FROM clause.  One slot of the
				** outer query (the middle slot) is used by the subquery.  The next
				** block of code will expand the out query to 4 slots.  The middle
				** slot is expanded to two slots in order to make space for the
				** two elements in the FROM clause of the subquery.
				*/
				if (nSubSrc > 1)
				{
					pParent.pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc - 1, iFrom + 1);
					//if ( db.mallocFailed != 0 )
					//{
					//  break;
					//}
				}

				/* Transfer the FROM clause terms from the subquery into the
				** outer query.
				*/
				for (i = 0; i < nSubSrc; i++)
				{
					sqlite3IdListDelete(db, ref pSrc.a[i + iFrom].pUsing);
					pSrc.a[i + iFrom] = pSubSrc.a[i];
					pSubSrc.a[i] = new SrcList_item();//memset(pSubSrc.a[i], 0, sizeof(pSubSrc.a[i]));
				}
				pSubitem = pSrc.a[iFrom]; // Reset for C#
				pSrc.a[iFrom].jointype = jointype;

				/* Now begin substituting subquery result set expressions for
				** references to the iParent in the outer query.
				**
				** Example:
				**
				**   SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
				**   \                     \_____________ subquery __________/          /
				**    \_____________________ outer query ______________________________/
				**
				** We look at every expression in the outer query and every place we see
				** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
				*/
				pList = pParent.pEList;
				for (i = 0; i < pList.nExpr; i++)
				{
					if (pList.a[i].zName == null)
					{
						string zSpan = pList.a[i].zSpan;
						if (ALWAYS(zSpan))
						{
							pList.a[i].zName = zSpan;// sqlite3DbStrDup( db, zSpan );
						}
					}
				}
				substExprList(db, pParent.pEList, iParent, pSub.pEList);
				if (isAgg)
				{
					substExprList(db, pParent.pGroupBy, iParent, pSub.pEList);
					pParent.pHaving = substExpr(db, pParent.pHaving, iParent, pSub.pEList);
				}
				if (pSub.pOrderBy != null)
				{
					Debug.Assert(pParent.pOrderBy == null);
					pParent.pOrderBy = pSub.pOrderBy;
					pSub.pOrderBy = null;
				}
				else if (pParent.pOrderBy != null)
				{
					substExprList(db, pParent.pOrderBy, iParent, pSub.pEList);
				}
				if (pSub.pWhere != null)
				{
					pWhere = sqlite3ExprDup(db, pSub.pWhere, 0);
				}
				else
				{
					pWhere = null;
				}
				if (subqueryIsAgg)
				{
					Debug.Assert(pParent.pHaving == null);
					pParent.pHaving = pParent.pWhere;
					pParent.pWhere = pWhere;
					pParent.pHaving = substExpr(db, pParent.pHaving, iParent, pSub.pEList);
					pParent.pHaving = sqlite3ExprAnd(db, pParent.pHaving,
					sqlite3ExprDup(db, pSub.pHaving, 0));
					Debug.Assert(pParent.pGroupBy == null);
					pParent.pGroupBy = sqlite3ExprListDup(db, pSub.pGroupBy, 0);
				}
				else
				{
					pParent.pWhere = substExpr(db, pParent.pWhere, iParent, pSub.pEList);
					pParent.pWhere = sqlite3ExprAnd(db, pParent.pWhere, pWhere);
				}

				/* The flattened query is distinct if either the inner or the
				** outer query is distinct.
				*/
				pParent.selFlags = (u16)(pParent.selFlags | pSub.selFlags & SF_Distinct);

				/*
				** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
				**
				** One is tempted to try to add a and b to combine the limits.  But this
				** does not work if either limit is negative.
				*/
				if (pSub.pLimit != null)
				{
					pParent.pLimit = pSub.pLimit;
					pSub.pLimit = null;
				}
			}

			/* Finially, delete what is left of the subquery and return
			** success.
			*/
			sqlite3SelectDelete(db, ref pSub);
			sqlite3SelectDelete(db, ref pSub1);
			return 1;
		}

#endif //* !SQLITE_OMIT_SUBQUERY) || !SQLITE_OMIT_VIEW) */

		/*
** Analyze the SELECT statement passed as an argument to see if it
** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if
** it is, or 0 otherwise. At present, a query is considered to be
** a min()/max() query if:
**
**   1. There is a single object in the FROM clause.
**
**   2. There is a single expression in the result set, and it is
**      either min(x) or max(x), where x is a column reference.
*/

		private static u8 minMaxQuery(Select p)
		{
			Expr pExpr;
			ExprList pEList = p.pEList;

			if (pEList.nExpr != 1)
				return WHERE_ORDERBY_NORMAL;
			pExpr = pEList.a[0].pExpr;
			if (pExpr.op != TK_AGG_FUNCTION)
				return 0;
			if (NEVER(ExprHasProperty(pExpr, EP_xIsSelect)))
				return 0;
			pEList = pExpr.x.pList;
			if (pEList == null || pEList.nExpr != 1)
				return 0;
			if (pEList.a[0].pExpr.op != TK_AGG_COLUMN)
				return WHERE_ORDERBY_NORMAL;
			Debug.Assert(!ExprHasProperty(pExpr, EP_IntValue));
			if (pExpr.u.zToken.Equals("min", StringComparison.OrdinalIgnoreCase))
			{
				return WHERE_ORDERBY_MIN;
			}
			else if (pExpr.u.zToken.Equals("max", StringComparison.OrdinalIgnoreCase))
			{
				return WHERE_ORDERBY_MAX;
			}
			return WHERE_ORDERBY_NORMAL;
		}

		/*
		** The select statement passed as the first argument is an aggregate query.
		** The second argment is the associated aggregate-info object. This
		** function tests if the SELECT is of the form:
		**
		**   SELECT count() FROM <tbl>
		**
		** where table is a database table, not a sub-select or view. If the query
		** does match this pattern, then a pointer to the Table object representing
		** <tbl> is returned. Otherwise, 0 is returned.
		*/

		private static Table isSimpleCount(Select p, AggInfo pAggInfo)
		{
			Table pTab;
			Expr pExpr;

			Debug.Assert(null == p.pGroupBy);

			if (p.pWhere != null || p.pEList.nExpr != 1
			|| p.pSrc.nSrc != 1 || p.pSrc.a[0].pSelect != null
			)
			{
				return null;
			}
			pTab = p.pSrc.a[0].pTab;
			pExpr = p.pEList.a[0].pExpr;
			Debug.Assert(pTab != null && null == pTab.pSelect && pExpr != null);

			if (IsVirtual(pTab))
				return null;
			if (pExpr.op != TK_AGG_FUNCTION)
				return null;
			if ((pAggInfo.aFunc[0].pFunc.flags & SQLITE_FUNC_COUNT) == 0)
				return null;
			if ((pExpr.flags & EP_Distinct) != 0)
				return null;

			return pTab;
		}

		/*
		** If the source-list item passed as an argument was augmented with an
		** INDEXED BY clause, then try to locate the specified index. If there
		** was such a clause and the named index cannot be found, return
		** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
		** pFrom.pIndex and return SQLITE_OK.
		*/

		private static int sqlite3IndexedByLookup(Parse pParse, SrcList_item pFrom)
		{
			if (pFrom.pTab != null && pFrom.zIndex != null && pFrom.zIndex.Length != 0)
			{
				Table pTab = pFrom.pTab;
				string zIndex = pFrom.zIndex;
				Index pIdx;
				for (pIdx = pTab.pIndex;
				pIdx != null && !pIdx.zName.Equals(zIndex, StringComparison.OrdinalIgnoreCase);
				pIdx = pIdx.pNext
				)
					;
				if (null == pIdx)
				{
					sqlite3ErrorMsg(pParse, "no such index: %s", zIndex);
					pParse.checkSchema = 1;
					return SQLITE_ERROR;
				}
				pFrom.pIndex = pIdx;
			}
			return SQLITE_OK;
		}

		/*
		** This routine is a Walker callback for "expanding" a SELECT statement.
		** "Expanding" means to do the following:
		**
		**    (1)  Make sure VDBE cursor numbers have been assigned to every
		**         element of the FROM clause.
		**
		**    (2)  Fill in the pTabList.a[].pTab fields in the SrcList that
		**         defines FROM clause.  When views appear in the FROM clause,
		**         fill pTabList.a[].x.pSelect with a copy of the SELECT statement
		**         that implements the view.  A copy is made of the view's SELECT
		**         statement so that we can freely modify or delete that statement
		**         without worrying about messing up the presistent representation
		**         of the view.
		**
		**    (3)  Add terms to the WHERE clause to accomodate the NATURAL keyword
		**         on joins and the ON and USING clause of joins.
		**
		**    (4)  Scan the list of columns in the result set (pEList) looking
		**         for instances of the "*" operator or the TABLE.* operator.
		**         If found, expand each "*" to be every column in every table
		**         and TABLE.* to be every column in TABLE.
		**
		*/

		private static int selectExpander(Walker pWalker, Select p)
		{
			Parse pParse = pWalker.pParse;
			int i, j, k;
			SrcList pTabList;
			ExprList pEList;
			SrcList_item pFrom;
			sqlite3 db = pParse.db;

			//if ( db.mallocFailed != 0 )
			//{
			//  return WRC_Abort;
			//}
			if (NEVER(p.pSrc == null) || (p.selFlags & SF_Expanded) != 0)
			{
				return WRC_Prune;
			}
			p.selFlags |= SF_Expanded;
			pTabList = p.pSrc;
			pEList = p.pEList;

			/* Make sure cursor numbers have been assigned to all entries in
			** the FROM clause of the SELECT statement.
			*/
			sqlite3SrcListAssignCursors(pParse, pTabList);

			/* Look up every table named in the FROM clause of the select.  If
			** an entry of the FROM clause is a subquery instead of a table or view,
			** then create a transient table ure to describe the subquery.
			*/
			for (i = 0; i < pTabList.nSrc; i++)// pFrom++ )
			{
				pFrom = pTabList.a[i];
				Table pTab;
				if (pFrom.pTab != null)
				{
					/* This statement has already been prepared.  There is no need
					** to go further. */
					Debug.Assert(i == 0);
					return WRC_Prune;
				}
				if (pFrom.zName == null)
				{
#if !SQLITE_OMIT_SUBQUERY
					Select pSel = pFrom.pSelect;
					/* A sub-query in the FROM clause of a SELECT */
					Debug.Assert(pSel != null);
					Debug.Assert(pFrom.pTab == null);
					sqlite3WalkSelect(pWalker, pSel);
					pFrom.pTab = pTab = new Table();// sqlite3DbMallocZero( db, sizeof( Table ) );
					if (pTab == null)
						return WRC_Abort;
					pTab.nRef = 1;
					pTab.zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", pTab);
					while (pSel.pPrior != null)
					{
						pSel = pSel.pPrior;
					}
					selectColumnsFromExprList(pParse, pSel.pEList, ref pTab.nCol, ref pTab.aCol);
					pTab.iPKey = -1;
					pTab.nRowEst = 1000000;
					pTab.tabFlags |= TF_Ephemeral;
#endif
				}
				else
				{
					/* An ordinary table or view name in the FROM clause */
					Debug.Assert(pFrom.pTab == null);
					pFrom.pTab = pTab =
					sqlite3LocateTable(pParse, 0, pFrom.zName, pFrom.zDatabase);
					if (pTab == null)
						return WRC_Abort;
					pTab.nRef++;
#if !(SQLITE_OMIT_VIEW) || !(SQLITE_OMIT_VIRTUALTABLE)
					if (pTab.pSelect != null || IsVirtual(pTab))
					{
						/* We reach here if the named table is a really a view */
						if (sqlite3ViewGetColumnNames(pParse, pTab) != 0)
							return WRC_Abort;

						pFrom.pSelect = sqlite3SelectDup(db, pTab.pSelect, 0);
						sqlite3WalkSelect(pWalker, pFrom.pSelect);
					}
#endif
				}
				/* Locate the index named by the INDEXED BY clause, if any. */
				if (sqlite3IndexedByLookup(pParse, pFrom) != 0)
				{
					return WRC_Abort;
				}
			}

			/* Process NATURAL keywords, and ON and USING clauses of joins.
			*/
			if ( /* db.mallocFailed != 0 || */ sqliteProcessJoin(pParse, p) != 0)
			{
				return WRC_Abort;
			}

			/* For every "*" that occurs in the column list, insert the names of
			** all columns in all tables.  And for every TABLE.* insert the names
			** of all columns in TABLE.  The parser inserted a special expression
			** with the TK_ALL operator for each "*" that it found in the column list.
			** The following code just has to locate the TK_ALL expressions and expand
			** each one to the list of all columns in all tables.
			**
			** The first loop just checks to see if there are any "*" operators
			** that need expanding.
			*/
			for (k = 0; k < pEList.nExpr; k++)
			{
				Expr pE = pEList.a[k].pExpr;
				if (pE.op == TK_ALL)
					break;
				Debug.Assert(pE.op != TK_DOT || pE.pRight != null);
				Debug.Assert(pE.op != TK_DOT || (pE.pLeft != null && pE.pLeft.op == TK_ID));
				if (pE.op == TK_DOT && pE.pRight.op == TK_ALL)
					break;
			}
			if (k < pEList.nExpr)
			{
				/*
				** If we get here it means the result set contains one or more "*"
				** operators that need to be expanded.  Loop through each expression
				** in the result set and expand them one by one.
				*/
				ExprList_item[] a = pEList.a;
				ExprList pNew = null;
				int flags = pParse.db.flags;
				bool longNames = (flags & SQLITE_FullColNames) != 0
				&& (flags & SQLITE_ShortColNames) == 0;

				for (k = 0; k < pEList.nExpr; k++)
				{
					Expr pE = a[k].pExpr;
					Debug.Assert(pE.op != TK_DOT || pE.pRight != null);
					if (pE.op != TK_ALL && (pE.op != TK_DOT || pE.pRight.op != TK_ALL))
					{
						/* This particular expression does not need to be expanded.
						*/
						pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
						if (pNew != null)
						{
							pNew.a[pNew.nExpr - 1].zName = a[k].zName;
							pNew.a[pNew.nExpr - 1].zSpan = a[k].zSpan;
							a[k].zName = null;
							a[k].zSpan = null;
						}
						a[k].pExpr = null;
					}
					else
					{
						/* This expression is a "*" or a "TABLE.*" and needs to be
						** expanded. */
						int tableSeen = 0;      /* Set to 1 when TABLE matches */
						string zTName;            /* text of name of TABLE */
						if (pE.op == TK_DOT)
						{
							Debug.Assert(pE.pLeft != null);
							Debug.Assert(!ExprHasProperty(pE.pLeft, EP_IntValue));
							zTName = pE.pLeft.u.zToken;
						}
						else
						{
							zTName = null;
						}
						for (i = 0; i < pTabList.nSrc; i++)//, pFrom++ )
						{
							pFrom = pTabList.a[i];
							Table pTab = pFrom.pTab;
							string zTabName = pFrom.zAlias;
							if (zTabName == null)
							{
								zTabName = pTab.zName;
							}
							///if ( db.mallocFailed != 0 ) break;
							if (zTName != null && !zTName.Equals(zTabName, StringComparison.OrdinalIgnoreCase))
							{
								continue;
							}
							tableSeen = 1;
							for (j = 0; j < pTab.nCol; j++)
							{
								Expr pExpr, pRight;
								string zName = pTab.aCol[j].zName;
								string zColname;  /* The computed column name */
								string zToFree;   /* Malloced string that needs to be freed */
								Token sColname = new Token();   /* Computed column name as a token */

								/* If a column is marked as 'hidden' (currently only possible
								** for virtual tables), do not include it in the expanded
								** result-set list.
								*/
								if (IsHiddenColumn(pTab.aCol[j]))
								{
									Debug.Assert(IsVirtual(pTab));
									continue;
								}

								if (i > 0 && (zTName == null || zTName.Length == 0))
								{
									int iDummy = 0;
									if ((pFrom.jointype & JT_NATURAL) != 0
									   && tableAndColumnIndex(pTabList, i, zName, ref iDummy, ref iDummy) != 0
									 )
									{
										/* In a NATURAL join, omit the join columns from the
										** table to the right of the join */
										continue;
									}
									if (sqlite3IdListIndex(pFrom.pUsing, zName) >= 0)
									{
										/* In a join with a USING clause, omit columns in the
										** using clause from the table on the right. */
										continue;
									}
								}
								pRight = sqlite3Expr(db, TK_ID, zName);
								zColname = zName;
								zToFree = "";
								if (longNames || pTabList.nSrc > 1)
								{
									Expr pLeft;
									pLeft = sqlite3Expr(db, TK_ID, zTabName);
									pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
									if (longNames)
									{
										zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
										zToFree = zColname;
									}
								}
								else
								{
									pExpr = pRight;
								}
								pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
								sColname.z = zColname;
								sColname.n = sqlite3Strlen30(zColname);
								sqlite3ExprListSetName(pParse, pNew, sColname, 0);
								sqlite3DbFree(db, ref zToFree);
							}
						}
						if (tableSeen == 0)
						{
							if (zTName != null)
							{
								sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
							}
							else
							{
								sqlite3ErrorMsg(pParse, "no tables specified");
							}
						}
					}
				}
				sqlite3ExprListDelete(db, ref pEList);
				p.pEList = pNew;
			}
			//#if SQLITE_MAX_COLUMN
			if (p.pEList != null && p.pEList.nExpr > db.aLimit[SQLITE_LIMIT_COLUMN])
			{
				sqlite3ErrorMsg(pParse, "too many columns in result set");
			}
			//#endif
			return WRC_Continue;
		}

		/*
		** No-op routine for the parse-tree walker.
		**
		** When this routine is the Walker.xExprCallback then expression trees
		** are walked without any actions being taken at each node.  Presumably,
		** when this routine is used for Walker.xExprCallback then
		** Walker.xSelectCallback is set to do something useful for every
		** subquery in the parser tree.
		*/

		private static int exprWalkNoop(Walker NotUsed, ref Expr NotUsed2)
		{
			UNUSED_PARAMETER2(NotUsed, NotUsed2);
			return WRC_Continue;
		}

		/*
		** This routine "expands" a SELECT statement and all of its subqueries.
		** For additional information on what it means to "expand" a SELECT
		** statement, see the comment on the selectExpand worker callback above.
		**
		** Expanding a SELECT statement is the first step in processing a
		** SELECT statement.  The SELECT statement must be expanded before
		** name resolution is performed.
		**
		** If anything goes wrong, an error message is written into pParse.
		** The calling function can detect the problem by looking at pParse.nErr
		** and/or pParse.db.mallocFailed.
		*/

		private static void sqlite3SelectExpand(Parse pParse, Select pSelect)
		{
			Walker w = new Walker();
			w.xSelectCallback = selectExpander;
			w.xExprCallback = exprWalkNoop;
			w.pParse = pParse;
			sqlite3WalkSelect(w, pSelect);
		}

#if !SQLITE_OMIT_SUBQUERY
		/*
** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo()
** interface.
**
** For each FROM-clause subquery, add Column.zType and Column.zColl
** information to the Table ure that represents the result set
** of that subquery.
**
** The Table ure that represents the result set was coned
** by selectExpander() but the type and collation information was omitted
** at that point because identifiers had not yet been resolved.  This
** routine is called after identifier resolution.
*/

		private static int selectAddSubqueryTypeInfo(Walker pWalker, Select p)
		{
			Parse pParse;
			int i;
			SrcList pTabList;
			SrcList_item pFrom;

			Debug.Assert((p.selFlags & SF_Resolved) != 0);
			if ((p.selFlags & SF_HasTypeInfo) == 0)
			{
				p.selFlags |= SF_HasTypeInfo;
				pParse = pWalker.pParse;
				pTabList = p.pSrc;
				for (i = 0; i < pTabList.nSrc; i++)//, pFrom++ )
				{
					pFrom = pTabList.a[i];
					Table pTab = pFrom.pTab;
					if (ALWAYS(pTab != null) && (pTab.tabFlags & TF_Ephemeral) != 0)
					{
						/* A sub-query in the FROM clause of a SELECT */
						Select pSel = pFrom.pSelect;
						Debug.Assert(pSel != null);
						while (pSel.pPrior != null)
							pSel = pSel.pPrior;
						selectAddColumnTypeAndCollation(pParse, pTab.nCol, pTab.aCol, pSel);
					}
				}
			}
			return WRC_Continue;
		}

#endif

		/*
** This routine adds datatype and collating sequence information to
** the Table ures of all FROM-clause subqueries in a
** SELECT statement.
**
** Use this routine after name resolution.
*/

		private static void sqlite3SelectAddTypeInfo(Parse pParse, Select pSelect)
		{
#if !SQLITE_OMIT_SUBQUERY
			Walker w = new Walker();
			w.xSelectCallback = selectAddSubqueryTypeInfo;
			w.xExprCallback = exprWalkNoop;
			w.pParse = pParse;
			sqlite3WalkSelect(w, pSelect);
#endif
		}

		/*
		** This routine sets of a SELECT statement for processing.  The
		** following is accomplished:
		**
		**     *  VDBE VdbeCursor numbers are assigned to all FROM-clause terms.
		**     *  Ephemeral Table objects are created for all FROM-clause subqueries.
		**     *  ON and USING clauses are shifted into WHERE statements
		**     *  Wildcards "*" and "TABLE.*" in result sets are expanded.
		**     *  Identifiers in expression are matched to tables.
		**
		** This routine acts recursively on all subqueries within the SELECT.
		*/

		private static void sqlite3SelectPrep(
		Parse pParse,         /* The parser context */
		Select p,             /* The SELECT statement being coded. */
		NameContext pOuterNC  /* Name context for container */
		)
		{
			if (NEVER(p == null))
				return;
			//sqlite3 db = pParse.db;
			if ((p.selFlags & SF_HasTypeInfo) != 0)
				return;
			sqlite3SelectExpand(pParse, p);
			if (pParse.nErr != 0 /*|| db.mallocFailed != 0 */ )
				return;
			sqlite3ResolveSelectNames(pParse, p, pOuterNC);
			if (pParse.nErr != 0 /*|| db.mallocFailed != 0 */ )
				return;
			sqlite3SelectAddTypeInfo(pParse, p);
		}

		/*
		** Reset the aggregate accumulator.
		**
		** The aggregate accumulator is a set of memory cells that hold
		** intermediate results while calculating an aggregate.  This
		** routine simply stores NULLs in all of those memory cells.
		*/

		private static void resetAccumulator(Parse pParse, AggInfo pAggInfo)
		{
			Vdbe v = pParse.pVdbe;
			int i;
			AggInfo_func pFunc;
			if (pAggInfo.nFunc + pAggInfo.nColumn == 0)
			{
				return;
			}
			for (i = 0; i < pAggInfo.nColumn; i++)
			{
				sqlite3VdbeAddOp2(v, OP_Null, 0, pAggInfo.aCol[i].iMem);
			}
			for (i = 0; i < pAggInfo.nFunc; i++)
			{//, pFunc++){
				pFunc = pAggInfo.aFunc[i];
				sqlite3VdbeAddOp2(v, OP_Null, 0, pFunc.iMem);
				if (pFunc.iDistinct >= 0)
				{
					Expr pE = pFunc.pExpr;
					Debug.Assert(!ExprHasProperty(pE, EP_xIsSelect));
					if (pE.x.pList == null || pE.x.pList.nExpr != 1)
					{
						sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one " +
						"argument");
						pFunc.iDistinct = -1;
					}
					else
					{
						KeyInfo pKeyInfo = keyInfoFromExprList(pParse, pE.x.pList);
						sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc.iDistinct, 0, 0,
						pKeyInfo, P4_KEYINFO_HANDOFF);
					}
				}
			}
		}

		/*
		** Invoke the OP_AggFinalize opcode for every aggregate function
		** in the AggInfo structure.
		*/

		private static void finalizeAggFunctions(Parse pParse, AggInfo pAggInfo)
		{
			Vdbe v = pParse.pVdbe;
			int i;
			AggInfo_func pF;
			for (i = 0; i < pAggInfo.nFunc; i++)
			{//, pF++){
				pF = pAggInfo.aFunc[i];
				ExprList pList = pF.pExpr.x.pList;
				Debug.Assert(!ExprHasProperty(pF.pExpr, EP_xIsSelect));
				sqlite3VdbeAddOp4(v, OP_AggFinal, pF.iMem, pList != null ? pList.nExpr : 0, 0,
				pF.pFunc, P4_FUNCDEF);
			}
		}

		/*
		** Update the accumulator memory cells for an aggregate based on
		** the current cursor position.
		*/

		private static void updateAccumulator(Parse pParse, AggInfo pAggInfo)
		{
			Vdbe v = pParse.pVdbe;
			int i;
			AggInfo_func pF;
			AggInfo_col pC;

			pAggInfo.directMode = 1;
			sqlite3ExprCacheClear(pParse);
			for (i = 0; i < pAggInfo.nFunc; i++)
			{//, pF++){
				pF = pAggInfo.aFunc[i];
				int nArg;
				int addrNext = 0;
				int regAgg;
				Debug.Assert(!ExprHasProperty(pF.pExpr, EP_xIsSelect));
				ExprList pList = pF.pExpr.x.pList;
				if (pList != null)
				{
					nArg = pList.nExpr;
					regAgg = sqlite3GetTempRange(pParse, nArg);
					sqlite3ExprCodeExprList(pParse, pList, regAgg, true);
				}
				else
				{
					nArg = 0;
					regAgg = 0;
				}
				if (pF.iDistinct >= 0)
				{
					addrNext = sqlite3VdbeMakeLabel(v);
					Debug.Assert(nArg == 1);
					codeDistinct(pParse, pF.iDistinct, addrNext, 1, regAgg);
				}
				if ((pF.pFunc.flags & SQLITE_FUNC_NEEDCOLL) != 0)
				{
					CollSeq pColl = null;
					ExprList_item pItem;
					int j;
					Debug.Assert(pList != null);  /* pList!=0 if pF->pFunc has NEEDCOLL */
					for (j = 0; pColl == null && j < nArg; j++)
					{//, pItem++){
						pItem = pList.a[j];
						pColl = sqlite3ExprCollSeq(pParse, pItem.pExpr);
					}
					if (pColl == null)
					{
						pColl = pParse.db.pDfltColl;
					}
					sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, pColl, P4_COLLSEQ);
				}
				sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF.iMem,
				pF.pFunc, P4_FUNCDEF);
				sqlite3VdbeChangeP5(v, (u8)nArg);
				sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
				sqlite3ReleaseTempRange(pParse, regAgg, nArg);
				if (addrNext != 0)
				{
					sqlite3VdbeResolveLabel(v, addrNext);
					sqlite3ExprCacheClear(pParse);
				}
			}

			/* Before populating the accumulator registers, clear the column cache.
			** Otherwise, if any of the required column values are already present
			** in registers, sqlite3ExprCode() may use OP_SCopy to copy the value
			** to pC->iMem. But by the time the value is used, the original register
			** may have been used, invalidating the underlying buffer holding the
			** text or blob value. See ticket [883034dcb5].
			**
			** Another solution would be to change the OP_SCopy used to copy cached
			** values to an OP_Copy.
			*/
			sqlite3ExprCacheClear(pParse);
			for (i = 0; i < pAggInfo.nAccumulator; i++)//, pC++)
			{
				pC = pAggInfo.aCol[i];
				sqlite3ExprCode(pParse, pC.pExpr, pC.iMem);
			}
			pAggInfo.directMode = 0;
			sqlite3ExprCacheClear(pParse);
		}

		/*
		** Add a single OP_Explain instruction to the VDBE to explain a simple
		** count() query ("SELECT count() FROM pTab").
		*/
#if !SQLITE_OMIT_EXPLAIN

		private static void explainSimpleCount(
		  Parse pParse,                  /* Parse context */
		  Table pTab,                    /* Table being queried */
		  Index pIdx                     /* Index used to optimize scan, or NULL */
		)
		{
			if (pParse.explain == 2)
			{
				string zEqp = sqlite3MPrintf(pParse.db, "SCAN TABLE %s %s%s(~%d rows)",
					pTab.zName,
					pIdx != null ? "USING COVERING INDEX " : "",
					pIdx != null ? pIdx.zName : "",
					pTab.nRowEst
				);
				sqlite3VdbeAddOp4(
					pParse.pVdbe, OP_Explain, pParse.iSelectId, 0, 0, zEqp, P4_DYNAMIC
				);
			}
		}

#else
//# define explainSimpleCount(a,b,c)
    static void explainSimpleCount(Parse a, Table b, Index c){}
#endif

		/*
    ** Generate code for the SELECT statement given in the p argument.
    **
    ** The results are distributed in various ways depending on the
    ** contents of the SelectDest structure pointed to by argument pDest
    ** as follows:
    **
    **     pDest.eDest    Result
    **     ------------    -------------------------------------------
    **     SRT_Output      Generate a row of output (using the OP_ResultRow
    **                     opcode) for each row in the result set.
    **
    **     SRT_Mem         Only valid if the result is a single column.
    **                     Store the first column of the first result row
    **                     in register pDest.iParm then abandon the rest
    **                     of the query.  This destination implies "LIMIT 1".
    **
    **     SRT_Set         The result must be a single column.  Store each
    **                     row of result as the key in table pDest.iParm.
    **                     Apply the affinity pDest.affinity before storing
    **                     results.  Used to implement "IN (SELECT ...)".
    **
    **     SRT_Union       Store results as a key in a temporary table pDest.iParm.
    **
    **     SRT_Except      Remove results from the temporary table pDest.iParm.
    **
    **     SRT_Table       Store results in temporary table pDest.iParm.
    **                     This is like SRT_EphemTab except that the table
    **                     is assumed to already be open.
    **
    **     SRT_EphemTab    Create an temporary table pDest.iParm and store
    **                     the result there. The cursor is left open after
    **                     returning.  This is like SRT_Table except that
    **                     this destination uses OP_OpenEphemeral to create
    **                     the table first.
    **
    **     SRT_Coroutine   Generate a co-routine that returns a new row of
    **                     results each time it is invoked.  The entry point
    **                     of the co-routine is stored in register pDest.iParm.
    **
    **     SRT_Exists      Store a 1 in memory cell pDest.iParm if the result
    **                     set is not empty.
    **
    **     SRT_Discard     Throw the results away.  This is used by SELECT
    **                     statements within triggers whose only purpose is
    **                     the side-effects of functions.
    **
    ** This routine returns the number of errors.  If any errors are
    ** encountered, then an appropriate error message is left in
    ** pParse.zErrMsg.
    **
    ** This routine does NOT free the Select structure passed in.  The
    ** calling function needs to do that.
    */
		private static SelectDest sdDummy = null;
		private static bool bDummy = false;

		private static int sqlite3Select(
		Parse pParse,         /* The parser context */
		Select p,             /* The SELECT statement being coded. */
		ref SelectDest pDest /* What to do with the query results */
		)
		{
			int i, j;               /* Loop counters */
			WhereInfo pWInfo;       /* Return from sqlite3WhereBegin() */
			Vdbe v;                 /* The virtual machine under construction */
			bool isAgg;             /* True for select lists like "count()" */
			ExprList pEList = new ExprList();      /* List of columns to extract. */
			SrcList pTabList = new SrcList();     /* List of tables to select from */
			Expr pWhere;            /* The WHERE clause.  May be NULL */
			ExprList pOrderBy;      /* The ORDER BY clause.  May be NULL */
			ExprList pGroupBy;      /* The GROUP BY clause.  May be NULL */
			Expr pHaving;           /* The HAVING clause.  May be NULL */
			bool isDistinct;        /* True if the DISTINCT keyword is present */
			int distinct;           /* Table to use for the distinct set */
			int rc = 1;             /* Value to return from this function */
			int addrSortIndex;      /* Address of an OP_OpenEphemeral instruction */
			AggInfo sAggInfo;       /* Information used by aggregate queries */
			int iEnd;               /* Address of the end of the query */
			sqlite3 db;             /* The database connection */

#if !SQLITE_OMIT_EXPLAIN
			int iRestoreSelectId = pParse.iSelectId;
			pParse.iSelectId = pParse.iNextSelectId++;
#endif

			db = pParse.db;
			if (p == null /*|| db.mallocFailed != 0 */ || pParse.nErr != 0)
			{
				return 1;
			}
#if !SQLITE_OMIT_AUTHORIZATION
if (sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0)) return 1;
#endif
			sAggInfo = new AggInfo();// memset(sAggInfo, 0, sAggInfo).Length;

			if (pDest.eDest <= SRT_Discard) //IgnorableOrderby(pDest))
			{
				Debug.Assert(pDest.eDest == SRT_Exists || pDest.eDest == SRT_Union ||
				pDest.eDest == SRT_Except || pDest.eDest == SRT_Discard);
				/* If ORDER BY makes no difference in the output then neither does
				** DISTINCT so it can be removed too. */
				sqlite3ExprListDelete(db, ref p.pOrderBy);
				p.pOrderBy = null;
				p.selFlags = (u16)(p.selFlags & ~SF_Distinct);
			}
			sqlite3SelectPrep(pParse, p, null);
			pOrderBy = p.pOrderBy;
			pTabList = p.pSrc;
			pEList = p.pEList;
			if (pParse.nErr != 0 /*|| db.mallocFailed != 0 */ )
			{
				goto select_end;
			}
			isAgg = (p.selFlags & SF_Aggregate) != 0;
			Debug.Assert(pEList != null);

			/* Begin generating code.
			*/
			v = sqlite3GetVdbe(pParse);
			if (v == null)
				goto select_end;

			/* If writing to memory or generating a set
			** only a single column may be output.
			*/
#if !SQLITE_OMIT_SUBQUERY
			if (checkForMultiColumnSelectError(pParse, pDest, pEList.nExpr))
			{
				goto select_end;
			}
#endif

			/* Generate code for all sub-queries in the FROM clause
*/
#if !SQLITE_OMIT_SUBQUERY || !SQLITE_OMIT_VIEW
			for (i = 0; p.pPrior == null && i < pTabList.nSrc; i++)
			{
				SrcList_item pItem = pTabList.a[i];
				SelectDest dest = new SelectDest();
				Select pSub = pItem.pSelect;
				bool isAggSub;

				if (pSub == null || pItem.isPopulated != 0)
					continue;

				/* Increment Parse.nHeight by the height of the largest expression
				** tree refered to by this, the parent select. The child select
				** may contain expression trees of at most
				** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
				** more conservative than necessary, but much easier than enforcing
				** an exact limit.
				*/
				pParse.nHeight += sqlite3SelectExprHeight(p);

				/* Check to see if the subquery can be absorbed into the parent. */
				isAggSub = (pSub.selFlags & SF_Aggregate) != 0;
				if (flattenSubquery(pParse, p, i, isAgg, isAggSub) != 0)
				{
					if (isAggSub)
					{
						isAgg = true;
						p.selFlags |= SF_Aggregate;
					}
					i = -1;
				}
				else
				{
					sqlite3SelectDestInit(dest, SRT_EphemTab, pItem.iCursor);
					Debug.Assert(0 == pItem.isPopulated);
					explainSetInteger(ref pItem.iSelectId, (int)pParse.iNextSelectId);
					sqlite3Select(pParse, pSub, ref dest);
					pItem.isPopulated = 1;
					pItem.pTab.nRowEst = (uint)pSub.nSelectRow;
				}
				//if ( /* pParse.nErr != 0 || */ db.mallocFailed != 0 )
				//{
				//  goto select_end;
				//}
				pParse.nHeight -= sqlite3SelectExprHeight(p);
				pTabList = p.pSrc;
				if (!(pDest.eDest <= SRT_Discard))//        if( null==IgnorableOrderby(pDest) )
				{
					pOrderBy = p.pOrderBy;
				}
			}
			pEList = p.pEList;
#endif
			pWhere = p.pWhere;
			pGroupBy = p.pGroupBy;
			pHaving = p.pHaving;
			isDistinct = (p.selFlags & SF_Distinct) != 0;

#if  !SQLITE_OMIT_COMPOUND_SELECT
			/* If there is are a sequence of queries, do the earlier ones first.
*/
			if (p.pPrior != null)
			{
				if (p.pRightmost == null)
				{
					Select pLoop, pRight = null;
					int cnt = 0;
					int mxSelect;
					for (pLoop = p; pLoop != null; pLoop = pLoop.pPrior, cnt++)
					{
						pLoop.pRightmost = p;
						pLoop.pNext = pRight;
						pRight = pLoop;
					}
					mxSelect = db.aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
					if (mxSelect != 0 && cnt > mxSelect)
					{
						sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
						goto select_end;
					}
				}
				rc = multiSelect(pParse, p, pDest);
				explainSetInteger(ref pParse.iSelectId, iRestoreSelectId);
				return rc;
			}
#endif

			/* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
** GROUP BY might use an index, DISTINCT never does.
*/
			Debug.Assert(p.pGroupBy == null || (p.selFlags & SF_Aggregate) != 0);
			if ((p.selFlags & (SF_Distinct | SF_Aggregate)) == SF_Distinct)
			{
				p.pGroupBy = sqlite3ExprListDup(db, p.pEList, 0);
				pGroupBy = p.pGroupBy;
				p.selFlags = (u16)(p.selFlags & ~SF_Distinct);
			}

			/* If there is both a GROUP BY and an ORDER BY clause and they are
			** identical, then disable the ORDER BY clause since the GROUP BY
			** will cause elements to come out in the correct order.  This is
			** an optimization - the correct answer should result regardless.
			** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
			** to disable this optimization for testing purposes.
			*/
			if (sqlite3ExprListCompare(p.pGroupBy, pOrderBy) == 0
			&& (db.flags & SQLITE_GroupByOrder) == 0)
			{
				pOrderBy = null;
			}

			/* If there is an ORDER BY clause, then this sorting
			** index might end up being unused if the data can be
			** extracted in pre-sorted order.  If that is the case, then the
			** OP_OpenEphemeral instruction will be changed to an OP_Noop once
			** we figure out that the sorting index is not needed.  The addrSortIndex
			** variable is used to facilitate that change.
			*/
			if (pOrderBy != null)
			{
				KeyInfo pKeyInfo;
				pKeyInfo = keyInfoFromExprList(pParse, pOrderBy);
				pOrderBy.iECursor = pParse.nTab++;
				p.addrOpenEphm[2] = addrSortIndex =
				sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
				pOrderBy.iECursor, pOrderBy.nExpr + 2, 0,
				pKeyInfo, P4_KEYINFO_HANDOFF);
			}
			else
			{
				addrSortIndex = -1;
			}

			/* If the output is destined for a temporary table, open that table.
			*/
			if (pDest.eDest == SRT_EphemTab)
			{
				sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest.iParm, pEList.nExpr);
			}

			/* Set the limiter.
			*/
			iEnd = sqlite3VdbeMakeLabel(v);
			p.nSelectRow = (double)LARGEST_INT64;
			computeLimitRegisters(pParse, p, iEnd);

			/* Open a virtual index to use for the distinct set.
			*/
			if ((p.selFlags & SF_Distinct) != 0)
			{
				KeyInfo pKeyInfo;
				Debug.Assert(isAgg || pGroupBy != null);
				distinct = pParse.nTab++;
				pKeyInfo = keyInfoFromExprList(pParse, p.pEList);
				sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
				pKeyInfo, P4_KEYINFO_HANDOFF);
				sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
			}
			else
			{
				distinct = -1;
			}

			/* Aggregate and non-aggregate queries are handled differently */
			if (!isAgg && pGroupBy == null)
			{
				/* This case is for non-aggregate queries
				** Begin the database scan
				*/
				pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, ref pOrderBy, 0);
				if (pWInfo == null)
					goto select_end;
				if (pWInfo.nRowOut < p.nSelectRow)
					p.nSelectRow = pWInfo.nRowOut;

				/* If sorting index that was created by a prior OP_OpenEphemeral
				** instruction ended up not being needed, then change the OP_OpenEphemeral
				** into an OP_Noop.
				*/
				if (addrSortIndex >= 0 && pOrderBy == null)
				{
					sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
					p.addrOpenEphm[2] = -1;
				}

				/* Use the standard inner loop
				*/
				Debug.Assert(!isDistinct);
				selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest,
				pWInfo.iContinue, pWInfo.iBreak);

				/* End the database scan loop.
				*/
				sqlite3WhereEnd(pWInfo);
			}
			else
			{
				/* This is the processing for aggregate queries */
				NameContext sNC;    /* Name context for processing aggregate information */
				int iAMem;          /* First Mem address for storing current GROUP BY */
				int iBMem;          /* First Mem address for previous GROUP BY */
				int iUseFlag;       /* Mem address holding flag indicating that at least
** one row of the input to the aggregator has been
** processed */
				int iAbortFlag;     /* Mem address which causes query abort if positive */
				int groupBySort;    /* Rows come from source in GR BY' clause thanROUP BY order */

				int addrEnd;        /* End of processing for this SELECT */

				/* Remove any and all aliases between the result set and the
				** GROUP BY clause.
				*/
				if (pGroupBy != null)
				{
					int k;                        /* Loop counter */
					ExprList_item pItem;          /* For looping over expression in a list */

					for (k = p.pEList.nExpr; k > 0; k--)//, pItem++)
					{
						pItem = p.pEList.a[p.pEList.nExpr - k];
						pItem.iAlias = 0;
					}
					for (k = pGroupBy.nExpr; k > 0; k--)//, pItem++ )
					{
						pItem = pGroupBy.a[pGroupBy.nExpr - k];
						pItem.iAlias = 0;
					}
					if (p.nSelectRow > (double)100)
						p.nSelectRow = (double)100;
				}
				else
				{
					p.nSelectRow = (double)1;
				}

				/* Create a label to jump to when we want to abort the query */
				addrEnd = sqlite3VdbeMakeLabel(v);

				/* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
				** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
				** SELECT statement.
				*/
				sNC = new NameContext(); // memset(sNC, 0, sNC).Length;
				sNC.pParse = pParse;
				sNC.pSrcList = pTabList;
				sNC.pAggInfo = sAggInfo;
				sAggInfo.nSortingColumn = pGroupBy != null ? pGroupBy.nExpr + 1 : 0;
				sAggInfo.pGroupBy = pGroupBy;
				sqlite3ExprAnalyzeAggList(sNC, pEList);
				sqlite3ExprAnalyzeAggList(sNC, pOrderBy);
				if (pHaving != null)
				{
					sqlite3ExprAnalyzeAggregates(sNC, ref pHaving);
				}
				sAggInfo.nAccumulator = sAggInfo.nColumn;
				for (i = 0; i < sAggInfo.nFunc; i++)
				{
					Debug.Assert(!ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect));
					sqlite3ExprAnalyzeAggList(sNC, sAggInfo.aFunc[i].pExpr.x.pList);
				}
				//      if ( db.mallocFailed != 0 ) goto select_end;

				/* Processing for aggregates with GROUP BY is very different and
				** much more complex than aggregates without a GROUP BY.
				*/
				if (pGroupBy != null)
				{
					KeyInfo pKeyInfo;  /* Keying information for the group by clause */
					int j1;             /* A-vs-B comparision jump */
					int addrOutputRow;  /* Start of subroutine that outputs a result row */
					int regOutputRow;   /* Return address register for output subroutine */
					int addrSetAbort;   /* Set the abort flag and return */
					int addrTopOfLoop;  /* Top of the input loop */
					int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
					int addrReset;      /* Subroutine for resetting the accumulator */
					int regReset;       /* Return address register for reset subroutine */

					/* If there is a GROUP BY clause we might need a sorting index to
					** implement it.  Allocate that sorting index now.  If it turns out
					** that we do not need it after all, the OpenEphemeral instruction
					** will be converted into a Noop.
					*/
					sAggInfo.sortingIdx = pParse.nTab++;
					pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
					addrSortingIdx = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
					sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
					0, pKeyInfo, P4_KEYINFO_HANDOFF);

					/* Initialize memory locations used by GROUP BY aggregate processing
					*/
					iUseFlag = ++pParse.nMem;
					iAbortFlag = ++pParse.nMem;
					regOutputRow = ++pParse.nMem;
					addrOutputRow = sqlite3VdbeMakeLabel(v);
					regReset = ++pParse.nMem;
					addrReset = sqlite3VdbeMakeLabel(v);
					iAMem = pParse.nMem + 1;
					pParse.nMem += pGroupBy.nExpr;
					iBMem = pParse.nMem + 1;
					pParse.nMem += pGroupBy.nExpr;
					sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag);
#if SQLITE_DEBUG
					VdbeComment(v, "clear abort flag");
#endif
					sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
#if SQLITE_DEBUG
					VdbeComment(v, "indicate accumulator empty");
#endif

					/* Begin a loop that will extract all source rows in GROUP BY order.
** This might involve two separate loops with an OP_Sort in between, or
** it might be a single loop that uses an index to extract information
** in the right order to begin with.
*/
					sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
					pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, ref pGroupBy, 0);
					if (pWInfo == null)
						goto select_end;
					if (pGroupBy == null)
					{
						/* The optimizer is able to deliver rows in group by order so
						** we do not have to sort.  The OP_OpenEphemeral table will be
						** cancelled later because we still need to use the pKeyInfo
						*/
						pGroupBy = p.pGroupBy;
						groupBySort = 0;
					}
					else
					{
						/* Rows are coming out in undetermined order.  We have to push
						** each row into a sorting index, terminate the first loop,
						** then loop over the sorting index in order to get the output
						** in sorted order
						*/
						int regBase;
						int regRecord;
						int nCol;
						int nGroupBy;

						explainTempTable(pParse,
						isDistinct && 0 == (p.selFlags & SF_Distinct) ? "DISTINCT" : "GROUP BY");

						groupBySort = 1;
						nGroupBy = pGroupBy.nExpr;
						nCol = nGroupBy + 1;
						j = nGroupBy + 1;
						for (i = 0; i < sAggInfo.nColumn; i++)
						{
							if (sAggInfo.aCol[i].iSorterColumn >= j)
							{
								nCol++;
								j++;
							}
						}
						regBase = sqlite3GetTempRange(pParse, nCol);
						sqlite3ExprCacheClear(pParse);
						sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, false);
						sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx, regBase + nGroupBy);
						j = nGroupBy + 1;
						for (i = 0; i < sAggInfo.nColumn; i++)
						{
							AggInfo_col pCol = sAggInfo.aCol[i];
							if (pCol.iSorterColumn >= j)
							{
								int r1 = j + regBase;
								int r2;
								r2 = sqlite3ExprCodeGetColumn(pParse,
								pCol.pTab, pCol.iColumn, pCol.iTable, r1);
								if (r1 != r2)
								{
									sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
								}
								j++;
							}
						}
						regRecord = sqlite3GetTempReg(pParse);
						sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
						sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord);
						sqlite3ReleaseTempReg(pParse, regRecord);
						sqlite3ReleaseTempRange(pParse, regBase, nCol);
						sqlite3WhereEnd(pWInfo);
						sqlite3VdbeAddOp2(v, OP_Sort, sAggInfo.sortingIdx, addrEnd);
#if SQLITE_DEBUG
						VdbeComment(v, "GROUP BY sort");
#endif
						sAggInfo.useSortingIdx = 1;
						sqlite3ExprCacheClear(pParse);
					}

					/* Evaluate the current GROUP BY terms and store in b0, b1, b2...
					** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth)
					** Then compare the current GROUP BY terms against the GROUP BY terms
					** from the previous row currently stored in a0, a1, a2...
					*/
					addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
					sqlite3ExprCacheClear(pParse);
					for (j = 0; j < pGroupBy.nExpr; j++)
					{
						if (groupBySort != 0)
						{
							sqlite3VdbeAddOp3(v, OP_Column, sAggInfo.sortingIdx, j, iBMem + j);
						}
						else
						{
							sAggInfo.directMode = 1;
							sqlite3ExprCode(pParse, pGroupBy.a[j].pExpr, iBMem + j);
						}
					}
					sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy.nExpr,
					pKeyInfo, P4_KEYINFO);
					j1 = sqlite3VdbeCurrentAddr(v);
					sqlite3VdbeAddOp3(v, OP_Jump, j1 + 1, 0, j1 + 1);

					/* Generate code that runs whenever the GROUP BY changes.
					** Changes in the GROUP BY are detected by the previous code
					** block.  If there were no changes, this block is skipped.
					**
					** This code copies current group by terms in b0,b1,b2,...
					** over to a0,a1,a2.  It then calls the output subroutine
					** and resets the aggregate accumulator registers in preparation
					** for the next GROUP BY batch.
					*/
					sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy.nExpr);
					sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
#if SQLITE_DEBUG
					VdbeComment(v, "output one row");
#endif
					sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd);
#if SQLITE_DEBUG
					VdbeComment(v, "check abort flag");
#endif
					sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
#if SQLITE_DEBUG
					VdbeComment(v, "reset accumulator");
#endif

					/* Update the aggregate accumulators based on the content of
** the current row
*/
					sqlite3VdbeJumpHere(v, j1);
					updateAccumulator(pParse, sAggInfo);
					sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
#if SQLITE_DEBUG
					VdbeComment(v, "indicate data in accumulator");
#endif
					/* End of the loop
*/
					if (groupBySort != 0)
					{
						sqlite3VdbeAddOp2(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop);
					}
					else
					{
						sqlite3WhereEnd(pWInfo);
						sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1);
					}

					/* Output the final row of result
					*/
					sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
#if SQLITE_DEBUG
					VdbeComment(v, "output final row");
#endif
					/* Jump over the subroutines
*/
					sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEnd);

					/* Generate a subroutine that outputs a single row of the result
					** set.  This subroutine first looks at the iUseFlag.  If iUseFlag
					** is less than or equal to zero, the subroutine is a no-op.  If
					** the processing calls for the query to abort, this subroutine
					** increments the iAbortFlag memory location before returning in
					** order to signal the caller to abort.
					*/
					addrSetAbort = sqlite3VdbeCurrentAddr(v);
					sqlite3VdbeAddOp2(v, OP_Integer, 1, iAbortFlag);
					VdbeComment(v, "set abort flag");
					sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
					sqlite3VdbeResolveLabel(v, addrOutputRow);
					addrOutputRow = sqlite3VdbeCurrentAddr(v);
					sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow + 2);
					VdbeComment(v, "Groupby result generator entry point");
					sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
					finalizeAggFunctions(pParse, sAggInfo);
					sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow + 1, SQLITE_JUMPIFNULL);
					selectInnerLoop(pParse, p, p.pEList, 0, 0, pOrderBy,
					distinct, pDest,
					addrOutputRow + 1, addrSetAbort);
					sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
					VdbeComment(v, "end groupby result generator");

					/* Generate a subroutine that will reset the group-by accumulator
					*/
					sqlite3VdbeResolveLabel(v, addrReset);
					resetAccumulator(pParse, sAggInfo);
					sqlite3VdbeAddOp1(v, OP_Return, regReset);
				} /* endif pGroupBy.  Begin aggregate queries without GROUP BY: */
				else
				{
					ExprList pDel = null;
#if !SQLITE_OMIT_BTREECOUNT
					Table pTab;
					if ((pTab = isSimpleCount(p, sAggInfo)) != null)
					{
						/* If isSimpleCount() returns a pointer to a Table structure, then
						** the SQL statement is of the form:
						**
						**   SELECT count() FROM <tbl>
						**
						** where the Table structure returned represents table <tbl>.
						**
						** This statement is so common that it is optimized specially. The
						** OP_Count instruction is executed either on the intkey table that
						** contains the data for table <tbl> or on one of its indexes. It
						** is better to execute the op on an index, as indexes are almost
						** always spread across less pages than their corresponding tables.
						*/
						int iDb = sqlite3SchemaToIndex(pParse.db, pTab.pSchema);
						int iCsr = pParse.nTab++;     /* Cursor to scan b-tree */
						Index pIdx;                   /* Iterator variable */
						KeyInfo pKeyInfo = null;      /* Keyinfo for scanned index */
						Index pBest = null;           /* Best index found so far */
						int iRoot = pTab.tnum;        /* Root page of scanned b-tree */

						sqlite3CodeVerifySchema(pParse, iDb);
						sqlite3TableLock(pParse, iDb, pTab.tnum, 0, pTab.zName);

						/* Search for the index that has the least amount of columns. If
						** there is such an index, and it has less columns than the table
						** does, then we can assume that it consumes less space on disk and
						** will therefore be cheaper to scan to determine the query result.
						** In this case set iRoot to the root page number of the index b-tree
						** and pKeyInfo to the KeyInfo structure required to navigate the
						** index.
						**
						** (2011-04-15) Do not do a full scan of an unordered index.
						**
						** In practice the KeyInfo structure will not be used. It is only
						** passed to keep OP_OpenRead happy.
						*/
						for (pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext)
						{
							if (pIdx.bUnordered == 0 && (null == pBest || pIdx.nColumn < pBest.nColumn))
							{
								pBest = pIdx;
							}
						}
						if (pBest != null && pBest.nColumn < pTab.nCol)
						{
							iRoot = pBest.tnum;
							pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest);
						}

						/* Open a read-only cursor, execute the OP_Count, close the cursor. */
						sqlite3VdbeAddOp3(v, OP_OpenRead, iCsr, iRoot, iDb);
						if (pKeyInfo != null)
						{
							sqlite3VdbeChangeP4(v, -1, pKeyInfo, P4_KEYINFO_HANDOFF);
						}
						sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
						sqlite3VdbeAddOp1(v, OP_Close, iCsr);
						explainSimpleCount(pParse, pTab, pBest);
					}
					else
#endif //* SQLITE_OMIT_BTREECOUNT */
					{
						/* Check if the query is of one of the following forms:
						**
						**   SELECT min(x) FROM ...
						**   SELECT max(x) FROM ...
						**
						** If it is, then ask the code in where.c to attempt to sort results
						** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause.
						** If where.c is able to produce results sorted in this order, then
						** add vdbe code to break out of the processing loop after the
						** first iteration (since the first iteration of the loop is
						** guaranteed to operate on the row with the minimum or maximum
						** value of x, the only row required).
						**
						** A special flag must be passed to sqlite3WhereBegin() to slightly
						** modify behavior as follows:
						**
						**   + If the query is a "SELECT min(x)", then the loop coded by
						**     where.c should not iterate over any values with a NULL value
						**     for x.
						**
						**   + The optimizer code in where.c (the thing that decides which
						**     index or indices to use) should place a different priority on
						**     satisfying the 'ORDER BY' clause than it does in other cases.
						**     Refer to code and comments in where.c for details.
						*/
						ExprList pMinMax = null;
						int flag = minMaxQuery(p);
						if (flag != 0)
						{
							Debug.Assert(!ExprHasProperty(p.pEList.a[0].pExpr, EP_xIsSelect));
							pMinMax = sqlite3ExprListDup(db, p.pEList.a[0].pExpr.x.pList, 0);
							pDel = pMinMax;
							if (pMinMax != null)///* && 0 == db.mallocFailed */ )
							{
								pMinMax.a[0].sortOrder = (u8)(flag != WHERE_ORDERBY_MIN ? 1 : 0);
								pMinMax.a[0].pExpr.op = TK_COLUMN;
							}
						}

						/* This case runs if the aggregate has no GROUP BY clause.  The
						** processing is much simpler since there is only a single row
						** of output.
						*/
						resetAccumulator(pParse, sAggInfo);
						pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, ref pMinMax, (byte)flag);
						if (pWInfo == null)
						{
							sqlite3ExprListDelete(db, ref pDel);
							goto select_end;
						}
						updateAccumulator(pParse, sAggInfo);
						if (pMinMax == null && flag != 0)
						{
							sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo.iBreak);
#if SQLITE_DEBUG
							VdbeComment(v, "%s() by index",
							(flag == WHERE_ORDERBY_MIN ? "min" : "max"));
#endif
						}
						sqlite3WhereEnd(pWInfo);
						finalizeAggFunctions(pParse, sAggInfo);
					}

					pOrderBy = null;
					sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
					selectInnerLoop(pParse, p, p.pEList, 0, 0, null, -1,
					pDest, addrEnd, addrEnd);

					sqlite3ExprListDelete(db, ref pDel);
				}
				sqlite3VdbeResolveLabel(v, addrEnd);
			} /* endif aggregate query */

			if (distinct >= 0)
			{
				explainTempTable(pParse, "DISTINCT");
			}

			/* If there is an ORDER BY clause, then we need to sort the results
			** and send them to the callback one by one.
			*/
			if (pOrderBy != null)
			{
				explainTempTable(pParse, "ORDER BY");
				generateSortTail(pParse, p, v, pEList.nExpr, pDest);
			}

			/* Jump here to skip this query
			*/
			sqlite3VdbeResolveLabel(v, iEnd);

			/* The SELECT was successfully coded.   Set the return code to 0
			** to indicate no errors.
			*/
			rc = 0;

		/* Control jumps to here if an error is encountered above, or upon
		** successful coding of the SELECT.
		*/
		select_end:
			explainSetInteger(ref pParse.iSelectId, iRestoreSelectId);

			/* Identify column names if results of the SELECT are to be output.
			*/
			if (rc == SQLITE_OK && pDest.eDest == SRT_Output)
			{
				generateColumnNames(pParse, pTabList, pEList);
			}

			sqlite3DbFree(db, ref sAggInfo.aCol);
			sqlite3DbFree(db, ref sAggInfo.aFunc);
			return rc;
		}

#if SQLITE_DEBUG
		/*
*******************************************************************************
** The following code is used for testing and debugging only.  The code
** that follows does not appear in normal builds.
**
** These routines are used to print out the content of all or part of a
** parse structures such as Select or Expr.  Such printouts are useful
** for helping to understand what is happening inside the code generator
** during the execution of complex SELECT statements.
**
** These routine are not called anywhere from within the normal
** code base.  Then are intended to be called from within the debugger
** or from temporary "printf" statements inserted for debugging.
*/

		private void sqlite3PrintExpr(Expr p)
		{
			if (!ExprHasProperty(p, EP_IntValue) && p.u.zToken != null)
			{
				sqlite3DebugPrintf("(%s", p.u.zToken);
			}
			else
			{
				sqlite3DebugPrintf("(%d", p.op);
			}
			if (p.pLeft != null)
			{
				sqlite3DebugPrintf(" ");
				sqlite3PrintExpr(p.pLeft);
			}
			if (p.pRight != null)
			{
				sqlite3DebugPrintf(" ");
				sqlite3PrintExpr(p.pRight);
			}
			sqlite3DebugPrintf(")");
		}

		private void sqlite3PrintExprList(ExprList pList)
		{
			int i;
			for (i = 0; i < pList.nExpr; i++)
			{
				sqlite3PrintExpr(pList.a[i].pExpr);
				if (i < pList.nExpr - 1)
				{
					sqlite3DebugPrintf(", ");
				}
			}
		}

		private void sqlite3PrintSelect(Select p, int indent)
		{
			sqlite3DebugPrintf("%*sSELECT(%p) ", indent, "", p);
			sqlite3PrintExprList(p.pEList);
			sqlite3DebugPrintf("\n");
			if (p.pSrc != null)
			{
				string zPrefix;
				int i;
				zPrefix = "FROM";
				for (i = 0; i < p.pSrc.nSrc; i++)
				{
					SrcList_item pItem = p.pSrc.a[i];
					sqlite3DebugPrintf("%*s ", indent + 6, zPrefix);
					zPrefix = "";
					if (pItem.pSelect != null)
					{
						sqlite3DebugPrintf("(\n");
						sqlite3PrintSelect(pItem.pSelect, indent + 10);
						sqlite3DebugPrintf("%*s)", indent + 8, "");
					}
					else if (pItem.zName != null)
					{
						sqlite3DebugPrintf("%s", pItem.zName);
					}
					if (pItem.pTab != null)
					{
						sqlite3DebugPrintf("(vtable: %s)", pItem.pTab.zName);
					}
					if (pItem.zAlias != null)
					{
						sqlite3DebugPrintf(" AS %s", pItem.zAlias);
					}
					if (i < p.pSrc.nSrc - 1)
					{
						sqlite3DebugPrintf(",");
					}
					sqlite3DebugPrintf("\n");
				}
			}
			if (p.pWhere != null)
			{
				sqlite3DebugPrintf("%*s WHERE ", indent, "");
				sqlite3PrintExpr(p.pWhere);
				sqlite3DebugPrintf("\n");
			}
			if (p.pGroupBy != null)
			{
				sqlite3DebugPrintf("%*s GROUP BY ", indent, "");
				sqlite3PrintExprList(p.pGroupBy);
				sqlite3DebugPrintf("\n");
			}
			if (p.pHaving != null)
			{
				sqlite3DebugPrintf("%*s HAVING ", indent, "");
				sqlite3PrintExpr(p.pHaving);
				sqlite3DebugPrintf("\n");
			}
			if (p.pOrderBy != null)
			{
				sqlite3DebugPrintf("%*s ORDER BY ", indent, "");
				sqlite3PrintExprList(p.pOrderBy);
				sqlite3DebugPrintf("\n");
			}
		}

		/* End of the structure debug printing code
		*****************************************************************************/
#endif // * defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */
	}
}